When developers first discover Supabase, it is usually pitched as an “open-source Firebase alternative.” But from an architectural standpoint, that comparison completely misses what makes the system unique.

Firebase relies on a proprietary NoSQL document store (Firestore) that forces developers to construct application logic around limited querying models, document denormalization, and vendor lock-in.

Supabase takes the exact opposite approach. Instead of building a custom database engine or obscuring the database behind a heavy abstraction layer, Supabase is simply PostgreSQL—wrapped by a modular suite of open-source microservices.

Every Supabase project is a dedicated, fully-featured Postgres database. The platform’s primary trick is turning native Postgres features (like Row Level Security, Write-Ahead Logs, schema catalogs, and extensions) into auto-generated APIs, real-time WebSocket streams, and unified identity systems.

The Supabase System Architecture

Supabase is not a single monolithic server. It is an orchestrated stack of independent open-source tools managed behind an API Gateway (Kong).

Supabase system architectureClient SDKs pass through Kong to modular API services, a connection pooler, and PostgreSQL. A realtime service reads database changes from the write-ahead log.Client layerREST SDK · GraphQL · WebSocketsKong API gatewayRouting · JWT validation · rate limitsPostgRESTREST · Haskellpg_graphqlGraphQL · RustGoTrue AuthIdentity · GoStorage APIObjects · S3 bridgeSupavisor / PgBouncerConnection pooling for serverless trafficPostgreSQL databaseRLS · WAL · schemas · extensionsRealtimeengineElixir · PhoenixWAL

How Supabase Connects to Postgres: The Core Components

To understand how Supabase turns a standard database into an end-to-end Backend-as-a-Service (BaaS), you have to trace how each underlying component interacts with Postgres.

1. The REST Layer: PostgREST

Instead of requiring developers to write CRUD endpoints manually (Express, Django, or FastAPI), Supabase uses PostgREST—a lightweight, stateless web server written in Haskell.

  • How it works: PostgREST inspects the Postgres information_schema catalog at startup. It dynamically generates RESTful endpoints for every table, view, and stored function in your public schema.
  • Why it’s fast: PostgREST translates incoming HTTP requests directly into single, highly optimized SQL queries (json_build_object / json_agg). The database executes the query and returns pre-formatted JSON directly to the client, avoiding object-relational mapping (ORM) overhead entirely.

2. The GraphQL Engine: pg_graphql

For developers who prefer GraphQL over REST, Supabase does not run an external GraphQL server. Instead, it uses `pg_graphql`, a native Postgres extension written in Rust.

  • How it works: The extension generates a GraphQL schema directly inside Postgres. When a GraphQL query hits the system, it executes a SQL function—graphql.resolve(...)—which parses the GraphQL AST and translates it into a single SQL statement natively inside the database query engine.

3. Authentication & JWTs: GoTrue

Supabase Auth is handled by GoTrue, a Go-based microservice for managing user signups, OAuth providers, MFA, and magic links.

  • How it connects to Postgres: GoTrue doesn’t store user credentials in a separate user database. It writes user records directly into a dedicated database schema inside your Postgres instance called auth.users.
  • The JWT Handshake: When a user logs in, GoTrue issues a signed JSON Web Token (JWT) containing the user’s UUID and role (e.g., authenticated or anon). This JWT is attached to every subsequent request header forwarded to PostgREST.
json
{  "sub": "a1b2c3d4-e5f6-7890-1234-56789abcdef0",  "role": "authenticated",  "email": "developer@zyloth.com",  "exp": 1721520000}

Authorization at the Core: Row Level Security (RLS)

In a traditional backend, security is enforced in application code. If a developer forgets an authorization check in a custom endpoint, data leaks. Supabase completely flips this model. Because client applications query PostgREST directly, authorization is pushed entirely into Postgres using native Row Level Security (RLS).

Traditional authorization compared with Supabase RLSA traditional backend checks authorization in an API server, while Supabase passes identity through PostgREST and lets PostgreSQL enforce row-level security.TRADITIONAL BACKENDClientAPI serverAuthorization checkDatabaseSuperuser accessSUPABASEClient + JWTPostgRESTSets JWT claimsPostgreSQLRLS policy enforced hereSIGNED JWTSQL QUERY

How RLS Works Under the Hood

When PostgREST handles a request with a user’s JWT:

  1. It opens a transaction inside Postgres.
  2. It sets local configuration variables for that transaction using SET LOCAL request.jwt.claims.
  3. Postgres evaluates the table’s SQL RLS Policy before returning or modifying any row.
sql
-- Example: Allow users to read only their own profileCREATE POLICY "Users can view own profile"ON public.profilesFOR SELECTUSING ( (SELECT auth.uid()) = user_id );

The function auth.uid() extracts the sub claim directly from the current transaction’s JWT claims. If the condition evaluates to false, Postgres omits the row from the result set. The API server doesn’t filter the data—the database query execution engine does.

Performance Optimization Note: A common pitfall in naive RLS policies is calling auth.uid() = user_id directly, which re-evaluates the function for every single row scanned. Wrapping the function in a subquery—(SELECT auth.uid()) = user_id—allows Postgres to cache the scalar result once per query, preventing massive execution slowdowns on large tables.

Realtime Streaming: Tapping into the Postgres WAL

How does Supabase broadcast live database changes (INSERTs, UPDATEs, DELETEs) over WebSockets without requiring custom trigger scripts on every table? It uses Postgres Logical Replication.

Supabase realtime event pipelineDatabase changes enter the Postgres write-ahead log, pass through a logical replication slot and the Elixir realtime engine, then reach authorized WebSocket clients.01INSERTUPDATE · DELETEData change02Postgres WALDurable log03ReplicationslotLogical decoding04Realtime engineElixir · Phoenix05WebSocketclientsAuthorized eventRLS-AWARE CHANGE BROADCAST
  1. Write-Ahead Log (WAL): Whenever data changes in Postgres, the transaction is first written sequentially to the WAL file on disk for durability.
  2. Logical Decoding: Supabase configures a logical replication slot on the database. The Realtime Engine—an Elixir server running on the Phoenix framework—connects to this replication slot.
  3. WAL to JSON: Realtime decodes binary WAL changes into structured JSON events using logical decoding plugins.
  4. Broadcast & Authorization: Realtime checks if the user listening on the WebSocket channel has permission to see the changed row (using a system called WALRUS to evaluate RLS against the streamed payload) and broadcasts the event over WebSockets to subscribed clients.

Connection Pooling: Supavisor & PgBouncer

Because PostgREST, client SDKs, Edge Functions, and serverless environments (Vercel, AWS Lambda) create bursty, short-lived connections, they can quickly exhaust PostgreSQL’s connection limits (where each connection spawns a dedicated OS process).

To prevent connection exhaustion, Supabase sits behind a connection pooler:

  • Supavisor: A cloud-native, multi-tenant Postgres connection pooler written in Elixir by Supabase, capable of managing millions of incoming client connections and proxying them down to a small, sustainable pool of physical Postgres connections.
  • PgBouncer: Used for co-located, single-tenant transaction pooling.

Summary: Component Breakdown

ComponentTech StackRole in Supabase Architecture
PostgreSQLCCentral engine; stores data, enforces RLS, executes logic
PostgRESTHaskellAuto-generates RESTful API directly from Postgres schema
`pg_graphql`Rust (PG Extension)Auto-generates GraphQL API natively inside Postgres
GoTrueGoHandles auth, OAuth providers, and issues signed JWTs
RealtimeElixir (Phoenix)Streams database changes from the WAL over WebSockets
SupavisorElixirHigh-performance connection pooler for serverless workloads
KongLua / NGINXAPI Gateway that unifies routing, SSL, and auth headers
Zyloth verdict

Final verdict

Supabase’s success stems from a clear architectural philosophy: do not hide PostgreSQL. By leveraging native Postgres primitives—Row Level Security for authorization, the Write-Ahead Log for real-time streaming, and `information_schema` for API generation—Supabase delivers the developer velocity of a turnkey backend without taking away direct SQL access, database portability, or relational power.

Inspect the repository