The Complete PocketBase Guide | Open Source Backend, SQLite, Realtime, Auth, Files, Production Use

The Complete PocketBase Guide | Open Source Backend, SQLite, Realtime, Auth, Files, Production Use

What this post covers

This is a complete guide to building a fast backend with PocketBase. It covers a single-binary setup, SQLite, realtime subscriptions, authentication, and file storage with practical examples.

From the field: After replacing a complex backend with PocketBase, infrastructure overhead disappeared and development speed increased roughly fivefold.

Introduction: “Backend setup is overwhelming”

Real-world scenarios

Scenario 1: Server setup is hard

Express plus database configuration is complex. PocketBase runs as a single file. Scenario 2: I need an admin panel

You would normally build it yourself. PocketBase ships with a built-in Admin UI. Scenario 3: Deployment is difficult

Complex infrastructure is often required. PocketBase deploys as a single binary.


1. What is PocketBase?

Core characteristics

PocketBase is an open-source backend. Key advantages:

  • Single binary: one executable
  • SQLite: embedded database
  • Admin UI: built-in management panel
  • Realtime: live subscriptions
  • Authentication: email, OAuth
  • File storage: built in

2. Installation and running

Download

# macOS/Linux
wget https://github.com/pocketbase/pocketbase/releases/download/v0.20.0/pocketbase_0.20.0_linux_amd64.zip
unzip pocketbase_0.20.0_linux_amd64.zip
# Run
./pocketbase serve

Admin UI

http://localhost:8090/_/

3. JavaScript SDK

Install

npm install pocketbase

Initialize

// lib/pocketbase.ts
import PocketBase from 'pocketbase';
export const pb = new PocketBase('http://localhost:8090');

4. CRUD

Create

The example below uses TypeScript with async/await. Run the code and verify the behavior step by step.

// Variable declaration and initialization
const record = await pb.collection('posts').create({
  title: 'My First Post',
  content: 'Hello PocketBase!',
  author: userId,
});

Read

The example below uses TypeScript with async/await. Review each part to understand its role.

// Fetch all
const records = await pb.collection('posts').getFullList();
// Fetch one
const record = await pb.collection('posts').getOne(recordId);
// Filtering
const records = await pb.collection('posts').getList(1, 20, {
  filter: 'published = true',
  sort: '-created',
});

Update

const record = await pb.collection('posts').update(recordId, {
  title: 'Updated Title',
});

Delete

await pb.collection('posts').delete(recordId);

5. Authentication

Sign up

The example below uses TypeScript with async/await. Run the code and verify the behavior step by step.

// Variable declaration and initialization
const record = await pb.collection('users').create({
  email: '[email protected]',
  password: 'password123',
  passwordConfirm: 'password123',
  name: 'John',
});

Sign in

The example below uses TypeScript with async/await. Run the code and verify the behavior step by step.

// Variable declaration and initialization
const authData = await pb.collection('users').authWithPassword(
  '[email protected]',
  'password123'
);
console.log(pb.authStore.token);
console.log(pb.authStore.model);

OAuth

const authData = await pb.collection('users').authWithOAuth2({
  provider: 'google',
});

Session management

The example below uses TypeScript. Review each part to understand its role.

// Current user
const user = pb.authStore.model;
// Sign out
pb.authStore.clear();
// React to session changes
pb.authStore.onChange((token, model) => {
  console.log('Auth changed:', token, model);
});

6. Realtime subscriptions

The example below uses TypeScript. Review each part to understand its role.

// Subscribe
pb.collection('posts').subscribe('*', (e) => {
  console.log('Event:', e.action, e.record);
});
// Subscribe to a specific record
pb.collection('posts').subscribe(recordId, (e) => {
  console.log('Record updated:', e.record);
});
// Unsubscribe
pb.collection('posts').unsubscribe();

React example

The following is a detailed TypeScript implementation: import the modules you need, use async flows where appropriate, and handle data in the component lifecycle. Review each part to understand its role.

'use client';
import { useEffect, useState } from 'react';
import { pb } from '@/lib/pocketbase';
export default function Posts() {
  const [posts, setPosts] = useState([]);
  useEffect(() => {
    fetchPosts();
    pb.collection('posts').subscribe('*', () => {
      fetchPosts();
    });
    return () => {
      pb.collection('posts').unsubscribe();
    };
  }, []);
  async function fetchPosts() {
    const records = await pb.collection('posts').getFullList();
    setPosts(records);
  }
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

7. File uploads

The example below uses TypeScript with async/await. Run the code and verify the behavior step by step.

const formData = new FormData();
formData.append('title', 'Post with Image');
formData.append('image', file);
const record = await pb.collection('posts').create(formData);
// File URL
const url = pb.files.getUrl(record, record.image);

8. Deployment

Docker

The example below uses a Dockerfile. Build and run it to verify the behavior.

FROM alpine:latest
RUN apk add --no-cache ca-certificates
COPY pocketbase /usr/local/bin/pocketbase
EXPOSE 8090
CMD ["/usr/local/bin/pocketbase", "serve", "--http=0.0.0.0:8090"]

Summary and checklist

Key takeaways

  • PocketBase: open-source backend
  • Single binary: one executable
  • SQLite: embedded database
  • Admin UI: built-in management panel
  • Realtime: live subscriptions
  • Authentication: email, OAuth

Implementation checklist

  • Download PocketBase
  • Run the server
  • Create collections
  • Implement CRUD
  • Implement authentication
  • Implement realtime subscriptions
  • Deploy

  • The Complete Supabase Guide
  • The Complete Convex Guide
  • SQLite guide

Keywords in this post

PocketBase, Backend, SQLite, Realtime, Auth, Open Source, Go

Frequently asked questions (FAQ)

Q. How does it compare to Supabase?

A. PocketBase is simpler and easier to self-host. Supabase is PostgreSQL-based and more powerful for large-scale workloads.

Q. Is it suitable for production?

A. Yes, for small and medium projects. For very large deployments, a PostgreSQL-based stack is often a better fit.

Q. Is it free?

A. Yes—it is fully open source and free to use.

Q. What about scalability?

A. It is SQLite-based and fits a single-server model well. For large-scale needs, Supabase is a common recommendation.