Supabase: The Open-Source Firebase Alternative That Hands You a Real Postgres Database

Supabase: The Open-Source Firebase Alternative That Hands You a Real Postgres Database

Supabase: The Open-Source Firebase Alternative That Hands You a Real Postgres Database

"Firebase gives you speed and takes your schema hostage. Supabase's bet is that you can have the speed without surrendering the database โ€” because underneath, it's just Postgres."
Every developer who has built on Firebase eventually hits the same wall: the moment your data becomes genuinely relational, or your bill scales with usage, or compliance asks where exactly the data lives. Supabase (GitHub: supabase/supabase) exists for that moment. It is an open-source backend platform that gives you a real PostgreSQL database plus authentication, auto-generated REST and GraphQL APIs, file storage, real-time subscriptions, and edge functions โ€” and lets you run the whole thing yourself. As of August 2026 it carries roughly 106,000 stars, ships under Apache-2.0, and was founded by Paul Copplestone and Ant Wilson through Y Combinator's S20 batch. For a blog about software you can run on your own hardware, it answers a question the self-hosting world rarely addresses well: can I get Firebase-grade developer speed without handing my data to a vendor? This is the honest breakdown โ€” how the component model works, why "it's just Postgres" is the central argument, what self-hosting actually costs, and the production hardening the official docs explicitly say you must do yourself. Supabase Studio dashboard over a Postgres database

1. What Supabase Is (and Isn't)

Supabase is a backend-as-a-service you can self-host. At its core is a PostgreSQL database. Layered on top are the things you'd otherwise build by hand: authentication (GoTrue), an auto-generated REST API (PostgREST), a GraphQL layer (pg_graphql), real-time change streams (Realtime, written in Elixir), file storage with policy-based access, and serverless edge functions (Deno-based). What it is not is a proprietary database. This distinction matters more than any feature list: Supabase does not put an abstraction layer between you and your data. You can connect with psql, use any ORM, run raw SQL, install Postgres extensions, and โ€” critically โ€” pg_dump your way out at any time. The project states this as a design principle: prefer portable standards over lock-in. It's also not a NoSQL document store. If your data is inherently hierarchical with no relational structure, forcing it into Postgres is a mistake, and the project's own guidance says so. Supabase is for teams who want relational integrity and a fast developer experience.

2. The Component Model: Lego, Not Monolith

The most underrated thing about Supabase's architecture is a design philosophy the team calls Isolation: every component should be able to run on its own. The internal test for whether a piece belongs in Supabase is literally "can a user run this product with nothing but a Postgres database?" That principle has a practical payoff for self-hosters. PostgREST works fine as a standalone REST layer over any Postgres database. GoTrue is a standalone auth server. If Supabase the company vanished tomorrow, the parts of your stack would keep working, and your data would still be a Postgres database you can administer with standard tools. The component stack: Postgres at the core, services around it The other three stated principles round it out: Integration (components should multiply each other's usefulness tenfold), Extensibility (prefer primitives over niche features โ€” "less, but better"), and Portability (prefer pg_dump and CSV over proprietary formats). Taken together they explain why the project leans so heavily on existing Postgres extensions: scheduled jobs are pg_cron, outbound webhooks are pg_net, vector search is pgvector, real-time change feeds ride on Postgres logical replication. Supabase didn't reimplement thirty years of database engineering โ€” it put an API in front of it.

3. Why "It's Just Postgres" Is the Whole Argument

Strip away the dashboard and this is the reason to choose Supabase: your data lives in a database that predates the company and will outlive it. That has three concrete consequences. You get the ecosystem. PostGIS for geospatial, TimescaleDB for time series, pgvector for embeddings, full-text search, JSONB, foreign keys, transactions, mature indexing โ€” all available, none requiring you to wait for a vendor to ship a feature. You get escape velocity. A pg_dump and a connection string is a migration path, not a rewrite. You get real relational modeling. Firebase's Firestore forces denormalization and client-side joins; Postgres gives you joins, constraints, and transactional guarantees. For AI-adjacent work specifically, pgvector means your relational data and your embeddings live in the same database โ€” one backup, one permission model, one query language. That's a genuinely simpler architecture than bolting a separate vector database onto your stack.

4. Row Level Security: Authorization Moves Into the Database

The feature that most changes how you build is Row Level Security (RLS). Instead of writing authorization middleware in your application, you express access rules as Postgres policies: ``sql -- Users can only read their own rows create policy "Users see own documents" on documents for select using ( auth.uid() = owner_id ); ` Because PostgREST exposes your database directly as an API, these policies are your API security. That's powerful โ€” access rules live next to the data, apply uniformly no matter which client connects, and can't be bypassed by a forgotten middleware check. It's also the single biggest footgun in the platform: a table with RLS enabled but no policy denies everything, and a table with RLS not enabled is readable by anyone with the anonymous key. Both mistakes have produced real data leaks. The same mechanism governs files. Storage permissions are Postgres policies too, so a file's access rule can call auth.uid() exactly like a row's can. Unifying row permissions and file permissions at the database layer is genuinely elegant โ€” and means that learning RLS properly is not optional, it's the core skill.

5. Self-Hosting: What You Actually Get

The official self-hosting path is Docker Compose with a set of overlays for different scenarios (reverse proxy, logging, S3 storage backends). It works, and the feature set is not artificially crippled โ€” Studio, the dashboard, is fully open source, which is a meaningful trust signal in a market where competitors keep their consoles proprietary. What you get: the complete platform on your own hardware, with your data never leaving your network. What you don't get is the managed platform's operational conveniences โ€” automated backups, point-in-time recovery, read replicas, log drains โ€” which are paid cloud features. Self-hosting means you own those responsibilities: secrets management, upgrades, backups, monitoring, and incident response. Worth quoting directly: the project's own documentation notes that the default self-hosted setup is not production-secure out of the box. You are expected to add a reverse proxy with TLS, rotate secrets, and harden before exposing it. That honesty is refreshing, and it's also a real workload that "just run the compose file" undersells.

6. The Cost, Honestly

Software: $0, Apache-2.0. Every component is open source and the self-hosted feature set is complete โ€” there is no enterprise tax on features. Hosting: the stack is not lightweight โ€” Postgres, plus GoTrue, PostgREST, Realtime (Elixir), Storage, Edge Runtime, Kong, and Studio. A realistic small production deployment wants a VPS with a few gigabytes of RAM: roughly $20โ€“$50/month, more as you scale. Managed cloud (for comparison): a free tier adequate for prototyping (around 500 MB database, 50K monthly active users, 1 GB storage), Pro at $25/month per project, Team at $599/month. The cost structure trap: pricing is per project, not per organization. Ten projects on Pro is $250/month before overages. Microservice or per-client database architectures get expensive fast โ€” which is exactly the situation where self-hosting starts to look very attractive. Your time: the largest line item for self-hosting. Multiple services, coordinated upgrades, Postgres backups, and RLS policy review. Budget an afternoon for a working stack and ongoing discipline thereafter.

7. Honest Limitations

  • Self-hosting is real ops work. Secrets, upgrades, backups, monitoring, incident response. The managed platform exists because this is genuinely hard.
  • Not production-secure by default. Reverse proxy with TLS, secret rotation, and hardening are on you.
  • RLS is unforgiving. Misconfigured policies are the most common cause of self-inflicted data exposure. Every table needs deliberate thought.
  • Per-project pricing on the hosted tier punishes multi-project setups.
  • Edge Function cold starts of roughly 200โ€“500ms after idle periods are noticeable for latency-sensitive endpoints.
  • No first-class offline sync. Firebase's Firestore handles offline-first mobile far better; with Supabase you build caching and sync yourself.
  • Compose-to-cloud drift. The self-hosted Compose schema and the managed platform are not identical, and moving a project between them can require manual reconfiguration (OAuth settings especially).
  • Realtime has scaling limits. Excessive websocket subscriptions can bottleneck at the Elixir Realtime layer.
  • Smaller ecosystem than Firebase โ€” fewer third-party tutorials, libraries, and niche documentation.
None of these are reasons to avoid it. They're the reasons to go in with a plan instead of a demo.

8. Getting Started

`bash

clone and bring up the stack

git clone --depth 1 https://github.com/supabase/supabase cd supabase/docker cp .env.example .env # then edit: set real secrets! docker compose up -d
` Then: (1) replace every default secret and key in .env โ€” this is not optional, (2) open Studio, (3) create a table and immediately write an RLS policy for it, (4) confirm the generated REST API respects that policy with the anonymous key, (5) put TLS in front before exposing anything. Do the security steps before you build features, not after โ€” retrofitting RLS across twenty tables is miserable.

9. Supabase vs the Alternatives

| | Supabase | Firebase | Appwrite | PocketBase | |---|---|---|---|---| | Database | Postgres | Firestore (NoSQL) | MariaDB | SQLite | | License | Apache-2.0 | proprietary | BSD-3-Clause | BSD/MIT | | Self-host | โœ… complete | โŒ impractical | โœ… simple | โœ… single binary | | Relational | โœ… full | โŒ | partial | partial | | RLS / policy auth | โœ… | rules-based | โœ… | โœ… | | Realtime | โœ… | โœ… | โœ… | โœ… | | Ops burden (self-host) | moderateโ€“high | N/A | low | very low | The short version: Supabase is the pick when you want relational integrity plus a managed-quality developer experience and you're willing to own the operations. Firebase wins on ecosystem and offline sync. Appwrite is a strong simpler alternative with broad SDK support. PocketBase is brilliant for small self-contained projects where a single binary and SQLite are exactly right.

10. Who Should Run It

Run it if: you've outgrown Firebase's data model, you want a real relational database with a fast API layer, compliance requires data to sit on infrastructure you control, or per-project SaaS pricing is starting to hurt. Skip self-hosting if: you need zero DevOps overhead โ€” use the managed tier instead, or reach for PocketBase. Also skip it if you won't invest in learning RLS; a half-configured instance is a data breach waiting to happen. For this blog's readers โ€” people running Immich, Vaultwarden, Home Assistant, and a Docker host โ€” Supabase is the piece that turns "I can host things" into "I can build things," with the data staying on hardware you own.

11. A Real Deployment Walkthrough

The sequence that avoids most pain: Step 1 โ€” secrets first. Generate real values for
POSTGRES_PASSWORD, JWT_SECRET, and the anonymous/service role keys before the first boot. Rotating these after data exists is annoying; shipping defaults is worse. Step 2 โ€” one table, one policy. Create your first table, enable RLS immediately, and write the policy in the same sitting. Building the habit early prevents the "we forgot RLS on six tables" audit later. Step 3 โ€” verify from the outside. Query the REST endpoint with the anonymous key and confirm you see only what the policy allows. Testing with the service-role key proves nothing, because it bypasses RLS entirely โ€” a common false sense of security. Step 4 โ€” TLS and backups. Reverse proxy with a certificate, then automated pg_dump to storage that isn't the same disk. Step 5 โ€” add features deliberately. Auth, then storage, then realtime, then edge functions. Each is a separate service with its own failure mode; adding them one at a time makes problems traceable.

12. Troubleshooting & Gotchas

  • "Permission denied for table" โ€” RLS is enabled with no matching policy. Expected behavior, not a bug; write the policy.
  • API returns everything to anonymous users โ€” RLS is not enabled on that table. This is the dangerous one. Audit every table.
  • Edge Functions are slow on first call โ€” cold start. Keep them warm or move latency-critical paths elsewhere.
  • Realtime subscriptions lag under load โ€” too many websocket subscriptions; consolidate channels and reconsider the fan-out pattern.
  • Upgrades break things โ€” multiple coupled services. Read release notes, snapshot volumes, and upgrade in a maintenance window.
  • Works locally, 401s behind the proxy โ€” usually SITE_URL or the API gateway configuration not matching your public URL.
The throughline of nearly every Supabase problem: it's either RLS, or it's networking between the services. Learn those two and the platform becomes predictable.

13. The Postgres Extension Ecosystem You Inherit

The most underrated benefit of "it's just Postgres" is that a decade of database engineering becomes available to you instantly, without waiting for anyone to ship a feature:
  • pgvector โ€” store and query embeddings next to your relational data. One backup, one permission model, one query language for both your rows and your vectors.
  • PostGIS โ€” full geospatial support for anything location-aware.
  • pg_cron โ€” scheduled jobs running inside the database, no separate scheduler to host.
  • pg_net โ€” make outbound HTTP calls from SQL, which is how database-triggered webhooks work.
  • pg_graphql โ€” a GraphQL API generated from your schema, no resolver code.
This is the practical meaning of the Integration principle: rather than reimplementing capabilities as proprietary services, Supabase exposes Postgres extensions as platform features. The consequence for a self-hoster is a much smaller surface area to operate โ€” instead of running a separate vector database, a job scheduler, and a webhook dispatcher, you have one database with extensions enabled. It also means your skills transfer. Anything you learn about Postgres tuning, indexing, or query planning applies directly. You are not learning a vendor's proprietary query language; you're learning SQL.

14. Proving the Exit Exists

The best test of any "no lock-in" claim is whether you can actually leave. With Supabase, the exit is refreshingly boring:
`bash

dump the whole database

pg_dump -h localhost -U postgres -d postgres -Fc -f backup.dump

restore it anywhere Postgres runs

pg_restore -h newhost -U postgres -d postgres backup.dump
` That's it. Your data is a standard Postgres dump restorable on any Postgres instance, anywhere. Your auth users live in Postgres tables. Your storage files are objects you can copy out with any S3-compatible tool. Your RLS policies are SQL you can read and port. Contrast that with a proprietary BaaS, where "export" often means a JSON blob of documents whose schema you now have to reverse-engineer and whose access rules you have to rewrite from scratch in application code. The portability principle isn't a marketing slogan here โ€” it's the difference between a migration being a weekend and a migration being a quarter. It's also the strongest possible argument for running it yourself: even if you never leave, the fact that you could changes the entire power dynamic.

15. Backups: What You Actually Need to Protect

A self-hosted Supabase instance has three distinct things worth backing up, and people routinely protect only one of them.
  • The database โ€” your actual data, plus your auth users and your RLS policies. pg_dump on a schedule, stored encrypted and off-box. This is non-negotiable and it's the one everybody remembers.
  • The storage bucket โ€” your uploaded files. These live outside Postgres, so a database dump does not capture them. Use any S3-compatible tool to sync the bucket, and don't discover this gap during an incident.
  • Your configuration โ€” .env secrets, Compose files, and any reverse proxy config. Without these, restoring the data is an archaeology exercise rather than a restore.
Test a restore, not just a backup. A pg_dump` you've never actually restored from is a hypothesis, not a backup โ€” and the failure mode is always the same: it turns out during an emergency that the dump was of the wrong database, or the restore needs an extension that isn't installed on the new host. One more consideration specific to this stack: because RLS policies live in the database, they come along with your dump automatically. That's a genuine advantage over application-layer authorization, where access rules live in code that can drift out of sync with the data it governs. Restore the database and your security model comes with it.

Related

Comments (0)

No comments yet. Be the first to comment!

Leave a Comment