Supabase vs Firebase vs PocketBase — Which Backend Should You Actually Pick in 2026
I've shipped projects on all three. Here's what nobody tells you about the real tradeoffs between Supabase, Firebase, and PocketBase.
I've been building full-stack apps for over 13 years. In the last two years alone, I've shipped production projects on Firebase, Supabase, and PocketBase. Not toy apps — actual products handling real users and real data.
Every "comparison" article I've read online misses the point. They compare feature checklists. Features don't matter when your auth flow breaks at 2 AM and you need to debug it before morning. What matters is how these tools behave when things get messy.
Here's what I've actually learned.
The Quick Context
All three are "backend-as-a-service" platforms that give you a database, authentication, and an API without writing server code. But they solve very different problems:
- Supabase is a hosted PostgreSQL database with auth, storage, and edge functions bolted on
- Firebase is Google's all-in-one platform built around a NoSQL document store (Firestore)
- PocketBase is a single-binary Go server with SQLite, auth, and file storage you self-host
If you're already reaching for one of these, this article will either confirm your instinct or save you from a painful migration later.
Database: This Is Where It Actually Matters
Supabase: PostgreSQL, No Compromises
Supabase runs full PostgreSQL. That means joins, foreign keys, transactions, window functions, CTEs — everything. If you've ever modeled data in a relational database, you already know how to use Supabase.
The Row Level Security (RLS) policies feel weird at first, but once you get them, they're incredible. You write security rules as SQL policies directly on your tables. No middleware, no extra auth checks in your API routes.
-- Only let users read their own data
CREATE POLICY "Users can view own data"
ON profiles FOR SELECT
USING (auth.uid() = user_id);
-- Let users insert only their own records
CREATE POLICY "Users can insert own data"
ON profiles FOR INSERT
WITH CHECK (auth.uid() = user_id);
The Studio dashboard is also solid. You get a full table editor, SQL runner, and can manage everything visually. For debugging, being able to just write SQL is priceless.
Where Supabase hurts: The free tier gives you 500MB database and 1GB file storage. That sounds like a lot until you start storing user avatars and file uploads. You'll hit the storage limit before the database limit almost every time.
Firebase: Fast Until It Isn't
Firestore is a document-based NoSQL database. Data is stored as collections of JSON-like documents. It's incredibly fast to prototype with — no schema, no migrations, just write an object and it's stored.
// Writing data is stupid simple
await setDoc(doc(db, "users", "user123"), {
name: "Piotr",
email: "piotr@example.com",
plan: "pro",
createdAt: serverTimestamp()
});
But here's what bites you: Firestore has no joins. You need to denormalize everything. That means if a user changes their name, you might need to update it in 15 different places. You'll write Cloud Functions to keep things in sync, and those Cloud Functions will occasionally fail silently.
The query limitations are also real. You can't do inequality filters on multiple fields in the same query. You can't do full-text search without a third-party service. If you're building anything with complex data relationships — a project management tool, an e-commerce platform, a CRM — Firestore will fight you.
Where Firebase shines: Real-time updates work out of the box. For chat apps, collaborative tools, and dashboards that need live data, Firestore's real-time listeners are still best-in-class.
PocketBase: SQLite Simplicity
PocketBase uses SQLite under the hood. One file, zero configuration. You define collections (tables) through a web UI or API, and PocketBase handles the schema.
# The entire backend. One binary, one command.
./pocketbase serve
It's shockingly capable for what it is. You get a visual admin panel, full CRUD API, real-time subscriptions, file uploads, and auth — all from a 30MB binary.
Where PocketBase hurts: SQLite is single-writer. If your app needs heavy concurrent writes (think: a popular collaborative tool), you'll hit performance walls. PocketBase is not designed for horizontal scaling. It's a single-server solution. That's fine for most projects, but if you're planning for scale, know the ceiling.
Authentication: The Thing That Will Ruin Your Weekend
Supabase Auth
Supabase ships a full auth system built on GoTrue. Email/password, magic links, OAuth providers (Google, GitHub, Discord, etc.), and phone auth via SMS.
The integration with RLS is the real selling point. Once a user is authenticated, their auth.uid() is automatically available in every database query through RLS policies. No token parsing, no middleware.
// Sign up
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'secure-password'
});
// The session is handled automatically
// All subsequent queries are scoped to this user via RLS
const { data: posts } = await supabase
.from('posts')
.select('*'); // RLS filters this automatically
The gotcha: email templates are basic and customizing them requires navigating the dashboard settings. Also, the free tier limits you to 50,000 monthly active users, which is generous.
Firebase Auth
Firebase Auth is mature and battle-tested. Google login, Apple login, phone auth, email/password, anonymous auth — it handles everything. The SDKs are polished and well-documented.
The issue is that Firebase Auth is separate from Firestore security rules. You configure auth in one place and security rules in another, using a custom DSL that's not quite JavaScript and not quite anything else:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}
This language is limited. Complex authorization logic becomes unreadable fast. I've spent hours debugging security rules that looked correct but had subtle scoping issues.
PocketBase Auth
PocketBase has built-in email/password auth and OAuth2 support. It stores users in a special users collection. API rules are defined per-collection using a filter syntax:
@request.auth.id != "" && @request.auth.id = user_id
It works, but the OAuth2 setup requires more manual configuration than Supabase or Firebase. If you need advanced auth flows (multi-factor, phone auth, SAML), PocketBase isn't there yet.
Hosting and Deployment
Supabase
Fully managed. Sign up, create a project, get a URL. The free tier includes two projects. Paid plans start at $25/month for the Pro tier, which removes the project pause (inactive free projects get paused after a week) and increases limits.
You can also self-host Supabase using Docker, but it's a constellation of services — Postgres, GoTrue, PostgREST, Realtime, Storage, Kong — and managing all of that yourself defeats the purpose for most people.
Firebase
Fully managed by Google. The Spark (free) plan is generous: 1GB Firestore storage, 10GB bandwidth, 50K daily reads. The Blaze (pay-as-you-go) plan scales automatically. You only pay for what you use.
The pricing model is where Firebase gets tricky. Firestore charges per document read/write/delete. If you have a dashboard that loads 10,000 documents on page load, that's 10,000 reads. Costs can spike unexpectedly if you're not careful with your queries.
PocketBase
Self-hosted only. No managed service exists. You need a VPS. The upside is cost: a $5/month DigitalOcean droplet or a Railway container handles PocketBase easily. The downside is you manage backups, SSL, updates, and uptime yourself.
Here's my typical PocketBase deployment on Railway:
FROM alpine:latest
ADD https://github.com/pocketbase/pocketbase/releases/download/v0.25.0/pocketbase_0.25.0_linux_amd64.zip /tmp/pb.zip
RUN unzip /tmp/pb.zip -d /pb/
EXPOSE 8080
CMD ["/pb/pocketbase", "serve", "--http=0.0.0.0:8080"]
Total cost: under $5/month. That's hard to beat.
Real-World Performance
I ran the same type of application (a task management app with auth, CRUD, file uploads, and real-time updates) on all three backends. Here's what I measured:
Cold start to first query:
- Supabase: ~200ms (managed Postgres is always warm on paid plans)
- Firebase: ~150ms (Google's infrastructure is fast)
- PocketBase on Railway: ~50ms (SQLite is local, no network hop to a separate DB)
List query (100 items with filtering):
- Supabase: ~80ms (PostgREST is efficient)
- Firebase: ~120ms (document fetch + client-side assembly)
- PocketBase: ~30ms (SQLite is fast for reads)
File upload (2MB image):
- Supabase: ~400ms (S3-compatible storage)
- Firebase: ~350ms (Cloud Storage)
- PocketBase: ~200ms (local filesystem)
PocketBase wins on raw speed because everything is local. But these numbers don't account for CDN, global distribution, or concurrent users — areas where managed services have a clear advantage.
My Actual Recommendations
Pick Supabase if you're building a production SaaS, need complex queries, or want a real database you can actually reason about. The combination of PostgreSQL + RLS + Edge Functions covers 90% of backend needs. I use it for most of my client projects now.
Pick Firebase if you need real-time sync as a core feature (collaborative tools, chat, live dashboards), you're building a mobile app (the native SDKs are excellent), or your team already knows the Google ecosystem.
Pick PocketBase if you're building an internal tool, a prototype, a personal project, or anything where you don't need to scale beyond a single server. The speed of development is unmatched. I use it for all my side projects and IoT dashboards.
The Migration Reality
One last thing nobody talks about: migration difficulty.
Moving off Firebase is painful. Your data model is likely denormalized in ways that don't translate to SQL. Your auth tokens are Firebase-specific. Your file storage uses Firebase URLs.
Moving off Supabase is easy. It's PostgreSQL. pg_dump, load it somewhere else, done. Your RLS policies won't transfer, but your data model and queries will.
Moving off PocketBase is moderate. SQLite exports are simple, but the auth system and API rules need to be rebuilt.
This matters more than people think. The first backend you pick might not be the last one you use.
Wrapping Up
There's no universal winner here. I've used all three in production and I keep coming back to Supabase for serious projects and PocketBase for quick builds. Firebase still has its place, but its NoSQL model creates more problems than it solves for most web apps.
The best advice I can give: think about your data model first. If your data has relationships (and it almost always does), start with Supabase. If you need speed and simplicity above all else, PocketBase is unbeatable. If real-time is your core feature, Firebase still does it best.
Stop reading comparison articles and just build something. You'll know within a week if you picked the right one.
Some links in this article are affiliate links. If you sign up through them, I may earn a small commission at no extra cost to you. I only recommend tools I actually use.