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: 'john@example.com',
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(
'john@example.com',
'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
Related reading
- 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.