PocketBase vs Supabase in 2026: Which Backend Platform?
PocketBase vs Supabase in 2026: Lightweight vs Full-Featured Backend
TL;DR
PocketBase and Supabase are both self-hosted Firebase alternatives, but they operate at completely different scales. PocketBase is a single 15 MB Go binary that contains an entire backend: auth, database (SQLite), file storage, real-time, and admin UI — zero configuration, 50 MB RAM. Supabase is a full platform built on PostgreSQL with unlimited scalability, a rich SDK ecosystem, edge functions, vector search, and horizontal scaling. For side projects and MVPs: PocketBase. For production applications with growth expectations: Supabase.
Key Takeaways
- PocketBase (MIT, 42K+ stars) is a single Go binary with embedded SQLite — your entire backend in one file, deployable in 30 seconds
- Supabase (Apache-2.0, 76K+ stars) is built on PostgreSQL — full SQL access, row-level security, vector search (pgvector), and unlimited horizontal scalability
- Firebase Spark (free tier) limits to 1 GB storage and 10 GB/month bandwidth; costs escalate fast with Blaze pay-as-you-go
- PocketBase uses SQLite — excellent for reads, limited for high-concurrency writes; PocketBase cannot horizontally scale
- Supabase self-hosted requires Docker with 4+ services and 2+ GB RAM; PocketBase runs in ~50 MB RAM
- Both offer auth (email + OAuth), file storage, real-time, and REST API
The Firebase Alternative Landscape
Firebase is the most developer-friendly backend-as-a-service, but its pricing model creates a problem: it starts free and becomes expensive at scale. Firebase Realtime Database charges $5/GB/month for storage and $1/GB for downloads. A moderately successful app with 100 GB storage and 500 GB monthly bandwidth pays $625/month — $7,500/year.
Supabase and PocketBase both eliminate per-unit Firebase pricing. You pay for infrastructure (a server) regardless of data volume.
PocketBase — Maximum Simplicity
PocketBase's design philosophy is radical minimalism: everything you need to build a backend, in one binary, with zero external dependencies.
# Complete PocketBase setup in 30 seconds
wget https://github.com/pocketbase/pocketbase/releases/latest/download/pocketbase_linux_amd64.zip
unzip pocketbase_linux_amd64.zip
./pocketbase serve --http="0.0.0.0:8090"
# Admin UI: http://localhost:8090/_/
# API: http://localhost:8090/api/
That's the entire installation. The binary starts an HTTP server, creates a SQLite database file, serves the admin UI, and begins accepting API requests. No Docker, no database server, no Redis, no configuration files.
Collection system is PocketBase's take on a database. You define "collections" with typed fields:
// PocketBase JavaScript SDK
import PocketBase from 'pocketbase';
const pb = new PocketBase('https://api.yourdomain.com');
// Authenticate
const authData = await pb.collection('users').authWithPassword(
'user@example.com',
'userpassword123'
);
// Create a record
const post = await pb.collection('posts').create({
title: 'Hello World',
content: 'My first post',
published: true,
author: authData.record.id,
});
// Query with filters
const posts = await pb.collection('posts').getList(1, 30, {
filter: 'published = true && author.name ~ "Alice"',
sort: '-created',
expand: 'author',
});
// Real-time subscription (SSE)
pb.collection('posts').subscribe('*', function(e) {
console.log(e.action); // create, update, delete
console.log(e.record); // the changed record
});
Go hooks enable custom business logic without a separate function runtime:
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/mailer"
)
func main() {
app := pocketbase.New()
// Hook: send welcome email on user creation
app.OnRecordAfterCreateSuccess("users").Add(func(e *core.RecordEvent) error {
message := &mailer.Message{
From: mail.Address{Name: "App", Address: "noreply@yourapp.com"},
To: []mail.Address{{Address: e.Record.Email()}},
Subject: "Welcome to our app!",
HTML: "<p>Thanks for signing up, " + e.Record.GetString("name") + "!</p>",
}
return app.NewMailClient().Send(message)
})
// Scheduled task
app.Cron().MustAdd("cleanup", "0 0 * * *", func() {
// Delete records older than 30 days
app.DB().NewQuery("DELETE FROM posts WHERE created < datetime('now', '-30 days')").Execute()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Key features:
- Single binary (~15 MB), zero dependencies
- SQLite database with typed collections
- Auth: email/password + 30+ OAuth providers
- File storage (local or S3)
- Real-time via SSE
- Admin UI
- JavaScript and Dart (Flutter) SDKs
- Go hooks for custom logic
- Auto-generated migrations
- REST API
- 50–100 MB RAM
- MIT license, 42K+ stars
PocketBase limitations:
- SQLite write concurrency — high-write applications (sustained concurrent writes) will hit SQLite's WAL limitations
- No horizontal scaling — one server, no clustering
- No full PostgreSQL SQL access
- No serverless functions in other languages
- No vector search
Supabase — Production-Ready Platform
Supabase chose PostgreSQL as its foundation and built an entire developer platform on top: REST API (via PostgREST), auth (GoTrue), real-time (via Postgres logical replication), storage (via S3-compatible service), and edge functions (Deno).
# Supabase self-hosted Docker Compose (simplified)
services:
kong:
image: kong:2.8.1
# API gateway routing to all services
ports:
- "8000:8000"
- "8443:8443"
auth:
image: supabase/gotrue:v2.140.0
environment:
GOTRUE_SITE_URL: https://app.yourdomain.com
GOTRUE_JWT_SECRET: your-jwt-secret
DATABASE_URL: postgres://supabase_auth_admin:password@db:5432/postgres
rest:
image: postgrest/postgrest:v12.0.2
environment:
PGRST_DB_URI: postgres://authenticator:password@db:5432/postgres
PGRST_JWT_SECRET: your-jwt-secret
PGRST_DB_SCHEMAS: public,storage
realtime:
image: supabase/realtime:v2.27.5
environment:
DB_HOST: db
DB_PASSWORD: password
JWT_SECRET: your-jwt-secret
storage:
image: supabase/storage-api:v0.46.4
environment:
PGSQL_CONNECTION_STRING: postgres://supabase_storage_admin:password@db:5432/postgres
FILE_STORAGE_BACKEND_PATH: /var/lib/storage
db:
image: supabase/postgres:15.1.0.147
environment:
POSTGRES_PASSWORD: password
volumes:
- supabase_db:/var/lib/postgresql/data
Full PostgreSQL access is Supabase's core differentiator. You're not working through a simplified API — you have the full power of PostgreSQL:
-- Row-Level Security: users can only read their own data
CREATE POLICY "Users can only view own data"
ON posts FOR SELECT
USING (auth.uid() = user_id);
-- Complex queries with JOINs, CTEs, window functions
WITH ranked_posts AS (
SELECT *,
RANK() OVER (PARTITION BY author_id ORDER BY likes DESC) as rank
FROM posts
WHERE created_at > NOW() - INTERVAL '30 days'
)
SELECT * FROM ranked_posts WHERE rank <= 3;
-- Full-text search
SELECT *
FROM articles
WHERE to_tsvector('english', title || ' ' || content) @@
to_tsquery('english', 'self-hosting & kubernetes');
Vector search via pgvector handles semantic search and AI features:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient('https://db.yourdomain.com', 'anon-key');
// Store embedding alongside document
const { data, error } = await supabase
.from('documents')
.insert({
content: articleText,
embedding: embeddingVector, // float[] from OpenAI/Mistral
});
// Semantic search: find similar documents
const { data: similar } = await supabase.rpc('match_documents', {
query_embedding: queryVector,
match_threshold: 0.78,
match_count: 10,
});
Edge functions handle serverless logic in Deno (TypeScript):
// supabase/functions/send-welcome-email/index.ts
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from "https://esm.sh/@supabase/supabase-js@2"
serve(async (req) => {
const { record } = await req.json()
// Send welcome email via Resend
await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('RESEND_API_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'App <noreply@yourapp.com>',
to: record.email,
subject: 'Welcome!',
html: `<p>Welcome ${record.name}!</p>`,
}),
})
return new Response('OK')
})
Key features:
- PostgreSQL with full SQL access
- Auto-generated REST API (PostgREST)
- Row-level security policies
- Auth: email/password + 50 OAuth providers + magic links + SSO
- Real-time via Postgres logical replication (WebSocket)
- File storage (S3-compatible)
- Edge functions (Deno/TypeScript)
- Vector search (pgvector extension)
- Database branching for dev/staging workflows
- PostgreSQL extensions (PostGIS, pg_cron, pg_partman, TimescaleDB)
- SDKs: JavaScript/TypeScript, Flutter, Swift, Kotlin, Python, C#, Go
- Apache-2.0 license, 76K+ stars
Side-by-Side Comparison
| Feature | PocketBase | Supabase |
|---|---|---|
| License | MIT | Apache-2.0 |
| Stars | 42K+ | 76K+ |
| Database | SQLite (embedded) | PostgreSQL |
| Setup time | 30 seconds | 10+ minutes |
| Min RAM | 50 MB | 2+ GB |
| Min containers | 1 | 8+ |
| Full SQL access | SQLite SQL | ✅ Full PostgreSQL |
| Horizontal scaling | ❌ | ✅ |
| Edge functions | ❌ (Go hooks only) | ✅ Deno |
| SDK breadth | JS, Dart | JS, Flutter, Swift, Kotlin, Python, C# |
| Vector search | ❌ | ✅ pgvector |
| PostgreSQL extensions | ❌ | ✅ |
| Cloud option | PocketHost | Supabase Cloud (free tier) |
Decision Framework
Choose PocketBase if:
- You're building a side project, MVP, internal tool, or mobile app prototype
- Deployment simplicity is paramount (single binary, no Docker required)
- Server resources are limited ($4/month VPS)
- Your app's scale is bounded — under ~100K monthly active users, single server
- Flutter/Dart SDK support is needed (PocketBase has excellent Dart SDK)
- You want Go-level control over business logic via hooks
Choose Supabase if:
- You're building a production application with growth expectations
- PostgreSQL features are important (RLS, extensions, complex queries)
- Horizontal scaling and high availability are requirements
- Vector search for AI features is on the roadmap
- You need multiple client SDKs (iOS + Android + Web)
- Serverless edge functions in TypeScript/Deno fit your architecture
Cost Comparison
| Scale | Firebase Blaze | PocketBase Self-Hosted | Supabase Self-Hosted |
|---|---|---|---|
| 1K MAU | ~$0 | $5/month | $20–30/month |
| 10K MAU | ~$50/month | $5/month | $20–30/month |
| 100K MAU | $200+/month | $15–20/month | $40–60/month |
Real-World Performance: When SQLite Becomes the Bottleneck
PocketBase's use of SQLite is its most discussed limitation, but the actual constraint is more nuanced than "SQLite doesn't scale." SQLite in WAL (Write-Ahead Logging) mode handles concurrent reads excellently — hundreds of simultaneous read operations are no problem. The limitation is concurrent writes. SQLite serializes writes at the database level, meaning only one write can proceed at a time. For most applications, this is irrelevant. For write-intensive applications — high-frequency event logging, real-time collaborative features, or any workflow involving many users submitting data simultaneously — you will eventually hit the ceiling.
The practical benchmark: a PocketBase instance on a modest VPS handles approximately 500-1,000 write operations per second under ideal conditions. This is more than enough for a SaaS product with thousands of users whose write patterns are distributed across time. It becomes a problem when you have bursts of simultaneous writes — a flash sale where 1,000 users submit orders simultaneously, or a real-time game where hundreds of players send state updates per second.
If your application has bursty write patterns, the mitigation options within PocketBase are limited. You can add application-level queuing to serialize writes in your Go hooks, which reduces the peak load on SQLite at the cost of increased latency. You can also pre-aggregate data so individual writes touch fewer records. But if the fundamental use case is high-concurrency writes, Supabase with PostgreSQL is the correct tool — PostgreSQL's MVCC (Multi-Version Concurrency Control) handles concurrent writes with true parallelism.
For applications that are read-heavy with moderate writes — which describes the vast majority of content platforms, portfolio sites, internal tools, and standard SaaS products — PocketBase's SQLite performance is entirely adequate and its simplicity advantage is compelling.
Auth System Depth Comparison
Both tools include authentication, but the depth and flexibility differ significantly.
PocketBase auth covers email/password, OAuth2 with 30+ providers (Google, GitHub, Discord, Twitter, Apple, Facebook, etc.), magic links, and TOTP (time-based one-time passwords). For most applications, this is everything you need. The auth model is collection-based: the users collection stores auth data alongside your application data. You can extend the users collection with custom fields — profile picture, subscription plan, onboarding status — and query it like any other collection. PocketBase's auth tokens are short-lived JWTs that the client SDK refreshes automatically.
What PocketBase lacks: SAML/SSO for enterprise customers, organization-level auth (multiple users under one account with role management), and advanced security features like IP allowlisting and session management across devices. For a B2B SaaS product where enterprise customers require SSO with Okta or Azure AD, PocketBase's auth is insufficient.
Supabase auth (powered by GoTrue) supports email/password, OAuth2, magic links, phone/SMS, and SAML 2.0 for enterprise SSO. The row-level security system integrates directly with auth — auth.uid() is available in RLS policies, letting you write database-level access rules like "users can only read their own records" without any application code. This is powerful and reduces an entire category of security bugs. Supabase also supports multi-factor authentication natively.
For applications that need to implement organization-level auth (a company account with multiple users and roles), Supabase requires you to build this layer yourself on top of its user model — it doesn't have a built-in "organizations" concept. This is a common requirement for B2B SaaS, and the implementation involves custom tables, RLS policies, and application logic. Services like Clerk and Stytch specialize in this if it's a core requirement.
Migration Paths Between Tools
One scenario worth planning for is outgrowing PocketBase and needing to migrate to Supabase. This migration is non-trivial but feasible.
The data migration path involves exporting PocketBase collections as JSON (PocketBase has a built-in export function), transforming the data to match your PostgreSQL schema, and importing via psql or Supabase's dashboard. The schema mapping between PocketBase's typed collections and PostgreSQL tables is generally direct — text fields, numbers, booleans, dates, and relations all have clear equivalents. PocketBase's file storage (if you're using local storage or S3) migrates independently.
The application code migration requires updating SDK calls. PocketBase's JavaScript SDK and Supabase's JavaScript SDK have different APIs — the migration involves rewriting data fetching, mutation, and subscription code throughout your application. Auth code needs updates too, since the token handling and OAuth flow implementations differ.
The honest assessment: if you build your application on PocketBase with the intention of migrating to Supabase later, the migration is a real engineering effort — not a weekend project. Building an abstraction layer over PocketBase from the start (so your application calls your own service layer rather than the PocketBase SDK directly) makes the migration easier but adds upfront complexity. For most projects, the better approach is to make the right tool choice upfront rather than planning to migrate.
For context on where these tools fit in the broader backend-as-a-service landscape, the Appwrite vs PocketBase comparison adds another dimension — Appwrite is a third option that sits between PocketBase's simplicity and Supabase's power. Understanding all three options helps clarify which is genuinely appropriate for your use case. The best open source alternatives to Supabase roundup covers the full landscape including Appwrite, PocketBase, and Firebase alternatives beyond just this direct comparison. If you're migrating from Firebase specifically, the Firebase to Supabase migration guide walks through the full data export, schema design, and auth migration process in detail.
Related: Best Open Source BaaS Platforms 2026 · Appwrite vs PocketBase · Supabase vs Appwrite
See open source alternatives to PocketBase on OSSAlt.