Most backends arrive as a stack: a database, an auth service, storage, an API gateway, a realtime engine, and Docker Compose glue. PocketBase replaces all of it with one binary — one download, no runtime to install — that gives you a database, authentication, file storage, realtime subscriptions, an admin dashboard, and a REST API the moment you run it. That radical simplicity has made it one of the most-starred open-source backends on GitHub and the default pick for solo developers, indie hackers, and internal tools.
Free tier at a glance
| Dimension | PocketBase (self-hosted) |
|---|---|
| Free quota / limits | None imposed by PocketBase — CPU, RAM, and disk depend entirely on your own server |
| Storage / records | Bounded only by your disk (SQLite file + uploads live in pb_data) |
| Projects / instances | Unlimited — run as many instances as your box can host |
| Sleeps / expires? | Never — it runs until you stop it; no trial, no inactivity pause |
| Commercial use | Allowed — MIT license, no fee, no seat or request cap |
| Region | Wherever your server is — you choose the machine's location |
| Credit card | None — no vendor account or signup; you only pay for the server |
| Download | One executable, roughly 12 MB zipped per platform (v0.40.1, 10 platform builds) |
What Is PocketBase?
PocketBase is an open-source backend packaged as a single Go binary. Inside that one file: an embedded SQLite database, a complete auth system, S3-compatible file storage, a realtime API, an admin dashboard, and an auto-generated REST API. It's created and maintained primarily by Gani Georgiev, and deliberately keeps its scope small. Source is on GitHub; docs at pocketbase.io/docs. As of mid-2026 it's at the v0.39.x series and still pre-1.0 — a detail covered honestly below.
The defining choice is "backend in one file." When you start it, PocketBase creates a pb_data directory holding your SQLite file and every uploaded asset. Back up that folder and you've backed up your entire application state. Three properties define how it feels:
- Zero-install. A compiled binary with no runtime dependency — no Node, Python, JVM, or Docker required. Download, unzip, run.
- Batteries included, admin-first. A polished dashboard at
http://127.0.0.1:8090/_/lets you define collections, set access rules, manage users, browse files, and read logs — no code to stand up a working API. - Two ways to grow. Simple apps use the auto-generated REST API and SDKs. For custom logic, extend with JavaScript hooks (no rebuild) or use PocketBase as a Go library (full type-safe control).
Is PocketBase Really Free?
Yes — and more cleanly than almost any "free tier" backend. PocketBase is MIT-licensed — confirmed against the repository, not just the marketing page — with no paid edition, no unlockable features, no seat limit, no request quota, and no telemetry. Because it self-hosts, the only cost is the server. Its own FAQ is blunt about how little it needs: "Even without optimizations, PocketBase can easily serve 10 000+ persistent realtime connections on a cheap $4 Hetzner CAX11 VPS (2vCPU, 4GB RAM)." That is the project's own figure, not a measurement of ours — but it is the ceiling they are willing to put in writing. A free-forever ARM VPS is wildly over-provisioned for it.
| Path | Monthly cost | What you get | The catch |
|---|---|---|---|
| Self-host on free VPS (e.g. Oracle Cloud Always Free) | $0 | No quotas — CPU/RAM/disk are the only limits | You manage the server, SSL, backups |
| Self-host on a $4–6 VPS | ~$4–6 | Full control, predictable price, no usage billing | Same ops responsibility, tiny bill |
| Managed host (e.g. PocketHost) | from ~$9.99/instance | No server to manage, backups handled | Paid — the free path is self-hosting |
Unlike a typical BaaS free tier that meters monthly active users, bandwidth, and function calls, PocketBase's ceiling is the hardware, not a pricing page. The trade is operational — nobody patches, backs up, or scales the box for you.
Core Features
Everything below ships inside the same single binary; nothing extra to install.
- Database and collections (SQLite). You model data as collections (tables) in three types: Base (normal table), View (read-only, backed by raw SQL), and Auth (records are users, with password/OAuth2 fields). Fields are strongly typed, and every collection gets a full CRUD REST API with filtering, sorting, and pagination. Because SQLite runs in-process, read-heavy workloads are genuinely fast — the trade-off is its single-writer model (see limits).
- Authentication + 20+ OAuth2 providers. Auth is a first-class collection type: email/password with verification and reset flows, plus OAuth2 sign-in for Google, GitHub, Apple, Microsoft, Discord, and more (20-plus), configured from the dashboard. It issues JWT tokens and supports OTP and multi-factor auth, with per-collection access rules.
- Realtime subscriptions. Any collection can be subscribed to. PocketBase pushes create/update/delete events over Server-Sent Events (SSE) — no polling, no separate websocket server. This is the feature behind the "10,000+ connections on a $4 VPS" number.
- File storage (local or S3). Attach a
filefield to any collection and PocketBase handles storage, serving, and on-the-fly thumbnails. Files default to localpb_data, but one config change points storage at any S3-compatible bucket (R2, B2, MinIO). - Admin dashboard + auto REST API. Create collections, define access rules, impersonate users, edit records, inspect logs, configure OAuth/mail, and trigger backups. Every collection is exposed at
http://127.0.0.1:8090/api/collections/<name>/records, with official JS and Dart SDKs.
Get Started in 60 Seconds
Grab the build for your platform from the GitHub releases page, unzip, and run:
# macOS / Linux
./pocketbase serve
# Windows
pocketbase.exe serve
That's the entire installation. It prints two URLs and opens an installer link to create your first superuser:
> Server started at http://127.0.0.1:8090
- REST API: http://127.0.0.1:8090/api/
- Dashboard: http://127.0.0.1:8090/_/
Open the dashboard, set admin credentials, and click "New collection" to create a posts collection. The moment you save, a working REST API exists — no migration, no restart.
Your First Records: the JavaScript SDK
The official pocketbase JS SDK works in the browser, Node, Deno, and React Native:
npm install pocketbase
import PocketBase from 'pocketbase';
const pb = new PocketBase('http://127.0.0.1:8090');
// 1. Sign a user in (email/password auth collection)
await pb.collection('users').authWithPassword(
'user@example.com',
'a-strong-password'
);
// 2. Create a record
const post = await pb.collection('posts').create({
title: 'Hello PocketBase',
content: 'A backend in one file.',
});
// 3. Query with filter, sort, and pagination
const page = await pb.collection('posts').getList(1, 20, {
filter: 'created >= "2026-01-01"',
sort: '-created',
});
// 4. Subscribe to realtime changes on the whole collection
pb.collection('posts').subscribe('*', (e) => {
console.log(e.action, e.record); // "create" | "update" | "delete"
});
OAuth2 sign-in is one call — pb.collection('users').authWithOAuth2({ provider: 'google' }) — once you've pasted the provider's client ID and secret into the dashboard.
Extending with JavaScript or Go
Real apps eventually need server-side logic. PocketBase offers two escape hatches.
JavaScript hooks (no rebuild). Drop .pb.js files into a pb_hooks directory to hook events, add routes, and schedule cron jobs — no compilation, no separate process:
// pb_hooks/main.pb.js
// Run logic after a new post is created
onRecordAfterCreateSuccess((e) => {
console.log('New post:', e.record.get('title'));
e.next();
}, 'posts');
// Add a custom API endpoint
routerAdd('GET', '/hello/{name}', (e) => {
return e.json(200, { message: 'Hello ' + e.request.pathValue('name') });
});
Go framework (maximum control). Import PocketBase into a main.go, register hooks with full type safety, and compile your code and PocketBase into one self-contained binary:
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnRecordAfterCreateSuccess("posts").BindFunc(func(e *core.RecordEvent) error {
log.Println("new post:", e.Record.GetString("title"))
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Reach for JS hooks for quick, deploy-anywhere customization; reach for the Go framework for compile-time safety and heavier logic.
Deploying for $0/Month
- Get a free VPS. An Oracle Cloud Always Free ARM instance (2 cores, 12 GB RAM after the June 2026 cut) is free and still over-spec for PocketBase. Any $4–6 VPS works too.
- Copy the binary, run under a service manager. Run it as a
systemdservice so it restarts on reboot/crash. PocketBase can auto-obtain a Let's Encrypt cert with./pocketbase serve yourdomain.comon port 443. - Set up automatic backups. The dashboard schedules backups of
pb_datato local disk or S3 — do this before you have real users.
# /etc/systemd/system/pocketbase.service
[Unit]
Description=PocketBase
After=network.target
[Service]
Type=simple
User=pocketbase
ExecStart=/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090
Restart=always
[Install]
WantedBy=multi-user.target
It also drops cleanly onto Fly.io, Railway, or any platform that runs a Docker container with a persistent volume at pb_data. The one rule that never changes: PocketBase needs a real persistent disk, so it doesn't fit stateless/ephemeral serverless platforms without external volume support.
What it actually costs to run (measured)
Everything above is what PocketBase says about itself. We ran v0.40.1 on an 8-core WSL2 Ubuntu box to put numbers on it. The scripts are linked at the end, so you can disagree with any figure by re-running it.
Standing it up
| Step | Measured |
|---|---|
| Download (linux_amd64 zip) | 12,529,377 bytes |
| Unpacked binary | 31 MB, and ldd reports “not a dynamic executable” — the “no dependencies” claim is literally true |
| Cold start to a responding API | 0.13 s |
| Idle resident memory | 29.8 MB |
First-run pb_data | 1.1 MB, of which 801 KB is a generated types.d.ts |
No package manager, no runtime to install, no container. One file, and an API answering in an eighth of a second.
Where the SQLite ceiling actually is
Every write-up about PocketBase repeats that SQLite serialises writes, and none of them says where that starts to matter. Firing 500 inserts at a time from a single process:
| Concurrent writers | Throughput | p50 latency | p95 |
|---|---|---|---|
| 1 | 1,101/s | 0.8 ms | 1.5 ms |
| 2 | 1,993/s | 0.8 ms | 1.9 ms |
| 4 | 2,516/s | 1.3 ms | 2.8 ms |
| 8 | 2,030/s | 3.4 ms | 7.4 ms |
| 16 | 2,220/s | 5.9 ms | 15.5 ms |
| 32 | 2,314/s | 10.6 ms | 24.8 ms |
Every request returned 200; all 3,000 rows landed. The shape is the finding: throughput stops improving after four concurrent writers, while latency keeps climbing — 0.8 ms at one writer, 10.6 ms at thirty-two. That is exactly what queueing behind a serialised resource looks like. Past four writers you are not buying throughput any more, only wait.
So the practical reading of “SQLite serialises writes” is not slow. Around 2,500 writes a second is a lot — more than most applications will ever ask for. It means write capacity does not grow when you add concurrency, so if your workload is genuinely write-saturated, the fix is a faster disk or a different database, never more app threads.
Reads behave the way SQLite readers are supposed to, scaling with concurrency instead of flattening early:
| Concurrent readers | Throughput | p50 latency |
|---|---|---|
| 1 | 664/s | 1.4 ms |
| 8 | 1,426/s | 4.1 ms |
| 16 | 2,178/s | 6.1 ms |
| 32 | 1,936/s | 9.8 ms |
Worth noting a single writer out-runs a single reader (1,101/s against 664/s): the read here is a paginated list query that also counts rows, while the insert is one row.
What 3,204 records cost
| Resource | After the load run |
|---|---|
data.db | 348 KB |
| Write-ahead log | 4.1 MB |
pb_data total | 13 MB |
| Resident memory | 46.6 MB (from 29.8 MB idle) |
Under 50 MB of RAM after three thousand writes. On the free ARM instances we cover in the Oracle Always Free writeup, that is a rounding error.
How not to measure this
Our first attempt used a shell loop with one curl per request and reported 140 writes/second. That number was about our own machine, not PocketBase: spawning a process per request costs about 6.5 ms, capping the harness near 155 requests/second, and reads and writes both duly “plateaued” just above it. Two independent tells gave it away — reads and writes hitting an identical ceiling, and a row count that did not match the number of inserts.
Rewritten as a single process with one reused connection per worker, the same instance did 1,101 writes/second single-threaded. The first harness was under-reporting by a factor of eight. If a benchmark shows a server answering in single-digit milliseconds, anything that forks per request is measuring the fork.
Reproduce it
bash automation/pocketbase_bench.sh # download, verify, start, time it
python3 automation/pocketbase_load.py # write and read ceilings
The download step checks the release’s own checksums.txt, which is not ceremony: on two of three runs the transfer was silently truncated — 11.9 MB of an expected 12.5 MB, with curl reporting success on one of them.
PocketBase vs Supabase vs Appwrite
The short version: Supabase gives you the full power of PostgreSQL, Appwrite gives you a Firebase-style document API with easy Docker self-hosting, and PocketBase gives you radical simplicity in one file.
| Dimension | PocketBase | Supabase | Appwrite |
|---|---|---|---|
| Database | SQLite (embedded) | PostgreSQL | MariaDB (document API) |
| Deployment | One binary, no Docker | Multi-service Docker stack | Docker Compose |
| Self-host complexity | Lowest | Highest | Medium |
| Horizontal scaling | No (vertical only) | Yes | App scales; single DB writer |
| Auth + OAuth2 | Built in, 20+ providers | Built in | Built in |
| Vector / AI search | Via SQLite extensions | Native pgvector | Limited |
| Managed free tier | No (self-host = free) | Yes | Yes |
| Best for | Solo apps, prototypes, internal tools on one server | Relational, multi-tenant SaaS that will scale | Mobile-first apps, Firebase-style DX |
Independent 2026 comparisons back the intuition: PocketBase leads on low-concurrency read latency because SQLite lives in-process, while Supabase pulls ahead on complex joins and high-concurrency writes. Choose based on where your app is headed, not just where it starts.
The Honest Limits
- Single server, vertical scaling only. No horizontal scaling, no built-in HA — you scale by giving the one box more CPU/RAM. If you need multiple app servers behind a load balancer sharing one database, PocketBase is the wrong tool.
- SQLite's single-writer model. We measured this: write throughput peaks at four concurrent writers (~2,500/s) and then stops improving while latency climbs from 0.8 ms to 10.6 ms. Fast in absolute terms, but write capacity does not grow with concurrency the way PostgreSQL's does, so a genuinely write-saturated workload needs a different database rather than more app threads.
- Pre-1.0 — and the warning is narrower than most write-ups claim. The latest release is v0.40.1 (24 August 2026). PocketBase does not tell you to keep it out of production; its README warns about one specific thing: "PocketBase is still under active development and therefore full backward compatibility is not guaranteed before reaching v1.0.0." The FAQ calls it "a great choice for small and midsize applications". So the cost is upgrade work, not reliability: read the changelog before you bump a version, because a minor release may ask you to migrate.
- No official managed cloud. You self-host or use a third-party host like PocketHost (paid). That's the price of no vendor lock-in.
Frequently Asked Questions
Is PocketBase free for commercial use?
Yes. It is MIT-licensed, which permits commercial use with no fee. Your only cost is the server you run it on, which can be a free-forever VPS.
Does PocketBase need Docker?
No. It is a single compiled binary with no runtime dependency. Docker is optional — handy for some hosting platforms, but never required. You can run ./pocketbase serve directly.
Can PocketBase handle production traffic?
For many apps, yes — its FAQ cites 10,000+ realtime connections on a $4 VPS. But it is pre-1.0 and self-manages, so read the changelog, automate backups, and understand the single-writer SQLite limit before betting a critical business on it.
How is PocketBase different from Firebase?
Firebase is a proprietary Google cloud service billed per operation with potential lock-in. PocketBase is open source, self-hosted, and free, with your data in a file you own — but without Firebase's managed global infrastructure and automatic scaling.
The Bottom Line
PocketBase answers a specific, common question: "I need a real backend — auth, database, files, realtime — but I don't want to run a distributed system or pay a per-user meter." One MIT-licensed binary delivers all of it, deploys onto a free VPS for $0/month, and stays out of your way. Respect its limits — single server, single writer, pre-1.0 — and for solo apps, prototypes, and internal tools it's one of the highest-leverage free tools a developer can reach for. When your ambitions outgrow one box, Supabase and Appwrite are waiting.
Related Reads
- Appwrite: Free Open-Source Backend (Firebase Alternative)
- Supabase vs Neon: Free PostgreSQL Database Compared
- Turso Free Tier: Hosted SQLite, 5GB and 100 DBs
- Oracle Cloud Always Free: 2-Core 12GB ARM VPS (Halved 2026)
- Coolify: Free Self-Hosted App Hosting (Your Own Heroku)
Version, licence and release details verified against the GitHub releases API and the project FAQ on 1 September 2026, when the current release was v0.40.1. PocketBase ships often — check the releases page rather than trusting a version number in any article, including this one.