PocketBase: The Open-Source Firebase Alternative That Runs in a Single Go Binary
You've built a side project. It needs a backend. You don't want to set up PostgreSQL, configure Redis, write auth from scratch, wrestle with Docker Compose, or pay Firebase prices when your user count grows.
What if the entire backend - database, realtime subscriptions, authentication, file storage, and an admin dashboard - was a single 15 MB Go binary?
That is PocketBase.
What PocketBase Actually Is
PocketBase is an open-source backend platform that packages everything into one statically linked executable:
- Embedded SQLite database with WAL mode and dual connection pools
- Realtime subscriptions via Server-Sent Events (SSE)
- Built-in authentication (email/password, OAuth2, MFA, passwordless)
- File storage with local or S3 backends
- Admin dashboard UI served from the same binary
- REST-ish API for all of the above
- Go framework - embed it in your own code for custom business logic
No separate database server. No Redis. No message queue. Just ./pocketbase serve and you're running.
The Architecture: How It Fits in One Binary
SQLite as the Foundation
PocketBase uses modernc.org/sqlite - a pure Go port of SQLite. No CGO required. This means:
- Cross-compilation works out of the box (
GOOS=linux GOARCH=amd64 go build) - Zero system dependencies at runtime
- The database file is just a file - copy it, back it up, move it anywhere
Dual Database Design
PocketBase maintains two separate SQLite databases:
| Database | File | Purpose |
|---|---|---|
| Main | data.db |
Collections, records, settings, auth data |
| Auxiliary | auxiliary.db |
Request logs, system metadata |
Why two? Log writes never block critical record operations. Backups are simpler - back up data.db without the noise. Both run in WAL mode with optimized pragmas.
Connection Pool Architecture: Solving SQLITE_BUSY
SQLite allows one writer at a time. PocketBase solves this with separate pools per database.
The nonconcurrent pool serializes all writes through a single connection. No lock contention. No SQLITE_BUSY errors. Reads scale across many connections.
Smart Query Routing: dualDBBuilder
PocketBase automatically routes queries based on SQL type.
During transactions, both pools point to the same *dbx.TX - routing is bypassed, atomicity guaranteed.
Realtime Subscriptions: SSE, Not WebSockets
PocketBase uses Server-Sent Events (SSE) - plain HTTP, no WebSocket upgrade handshake.
Why SSE?
- Works through every proxy, load balancer, and corporate firewall
- Automatic reconnection built into browsers (
EventSourceAPI) - Simpler server implementation - just a long-lived
GET /api/realtime - Unified API: writes go through regular REST endpoints, reads through SSE
How It Works
-
Client connects ->
GET /api/realtime-> receivesPB_CONNECTwithclientId -
Client subscribes ->
POST /api/realtimewith subscriptions - Server broadcasts on record create/update/delete -> checks access rules -> sends SSE event
Chunked iteration (150 clients per goroutine) + errgroup = horizontal scaling without blocking the event loop.
Authentication: Batteries Included
PocketBase handles the auth flows most teams rebuild poorly:
| Feature | Implementation |
|---|---|
| Email/password | Bcrypt, email verification, password reset |
| OAuth2 providers | Google, GitHub, Apple, Discord, etc. - 20+ built-in |
| MFA (TOTP) | RFC 6238, QR code generation, backup codes |
| Passwordless | Magic links, OTP via email/SMS |
| Token management | JWT access tokens + refresh tokens, configurable expiry |
| Auth collections | Any collection can be an auth collection |
Auth records are just records in a collection with type: "auth". The same API rules control access.
File Storage: Local or S3
Files attach to records via file field type. Storage backend is swappable.
Uploads are streaming - large files don't load into memory. Served via signed URLs or public access with token-based auth.
The Admin Dashboard: Not an Afterthought
Visit http://localhost:8090/_/ - you get:
- Collection schema editor (drag-and-drop field types)
- Record browser with filters, sorting, inline edit
- User management (auth collections)
- Settings UI (mail, S3, rate limits, CORS, logs)
- API playground with auto-generated request snippets
- Real-time log viewer
Built with Vue 3 + TypeScript, embedded as static assets in the binary.
Extending PocketBase: Go Framework Mode
Don't like something? Hook into it. PocketBase exposes custom routes, event hooks, and cron jobs.
Build your custom binary: go build -o myapp -> single executable with your logic baked in.
When PocketBase Shines (And When It Doesn't)
Great For
- Side projects & MVPs - zero infra, deploy to a $5 VPS
- Mobile app backends - realtime sync, offline-first friendly
- Internal tools - admin UI included, auth done
- Prototypes - schema changes via UI, instant feedback
- Low-to-moderate write throughput - SQLite handles thousands of writes/sec on SSD
Not Ideal For
- High-concurrency write-heavy workloads - SQLite serializes writers
- Horizontal scaling - single-node architecture
- Complex relational queries - no JOINs across collections
- Multi-region active-active - not designed for geo-distribution
Quick Start: 30 Seconds to Running Backend
# Download prebuilt binary (Linux/macOS/Windows)
curl -L https://github.com/pocketbase/pocketbase/releases/download/v0.23.0/pocketbase_0.23.0_linux_amd64.zip -o pb.zip
unzip pb.zip
./pocketbase serve --http=0.0.0.0:8090
Open http://localhost:8090/_/ -> create admin -> create collections -> done.
Or embed in Go with custom routes and hooks.
The Mental Model Shift
Most developers think "backend = separate services." PocketBase proves that for a huge class of applications, a single binary with SQLite is not a toy - it's the right architecture.
You get:
- Zero operational burden - no services to monitor, no config drift
- Portability - copy the binary + data dir, run anywhere
- Speed - no network hops between app and DB
- Simplicity - one codebase, one deploy artifact, one thing to understand
The trade-off is deliberate: you accept single-node limits in exchange for radical simplicity. For most projects, that's the correct trade-off.
Resources
- GitHub: pocketbase/pocketbase - 39k+ stars
- Docs: pocketbase.io/docs
- Demo: demo.pocketbase.io
- Discord: Active community for questions and showcase
Stop over-engineering your backend. Download PocketBase, run it, build your product.
Top comments (0)