The short version
- Supabase is a Postgres platform. Every project is a Postgres database. It layers auto-generated REST and GraphQL APIs, auth, storage, Edge Functions and a realtime channel on top.
- Concile is a reactive backend. You write TypeScript functions. Every query is live. Authorization is code. The database is a detail you pick with a flag.
- Supabase wins on the Postgres ecosystem and on being a hosted product. Concile wins on live queries, on unit-testable authorization, and on running as one process.
Side by side
| Concile | Supabase | |
|---|---|---|
| Live results from your own server code | Yes, read-set precise | Partly, row change events |
| Backend is plain TypeScript functions | Yes, query, mutation, action | Partly, Edge Functions off to the side |
| Authorization is ordinary code, not a rules language | Yes, functions you can unit test | No, row-level security in SQL |
| Self-host the whole product | Yes, one process, one command | Partly, several composed services |
| Single binary with no database to run | Yes | No, Postgres required |
| Swap the database without touching app code | Yes, SQLite or Postgres | No, Postgres only |
| Durable workflows with rollback | Yes, saga compensation | No, bring your own |
| Offline writes that survive a reload | Yes, durable outbox | No |
| Full-text and vector search | Not built yet | Yes, tsvector and pgvector |
| Hosted cloud | None | Yes |
| Price | Free to self-host | Free tier; Pro from $25 per month; Team from $599 per month; compute billed per project on top |
Live query versus change feed
Supabase Realtime has three primitives. Broadcast is for messages between clients. Presence shows who is online. Postgres Changes streams row events off the database. A row event tells you a row changed. It does not tell you whether that row still belongs in the filtered, joined, or sorted list your screen shows. Anything beyond watching a whole table is the client's job to work out.
In Concile, the query is the subscription. The server records what the query read. It notices when a commit touches it. Then it re-runs the query and pushes the correct result. The client never re-derives anything. This is what realtime by default means.
Authorization: code versus SQL policies
Supabase authorization uses Postgres Row Level Security. These are policies written in SQL. You write one per operation per table. The database enforces them on every access. Supabase's own docs describe why this is hard to get right. A table in an exposed schema without RLS enabled is readable and writable by any role with a grant. Views bypass RLS unless security_invoker is set. Two tables with policies that reference each other raise a recursion error. Supabase recommends a pgTAP test file for each protected table. There is no other way to know the policies do what you meant.
In Concile, authorization is a function. It runs in the same transaction as the read or write. It is type-checked with the rest of your app. You unit test it like anything else. Row policies are available through @concile/authz if you want them composed for you.
Deploying it yourself
Supabase's core is open source. You can self-host it with Docker Compose or the CLI. This includes Studio. You run Postgres and the services around it. These services include PostgREST, pg_graphql, Realtime, GoTrue for auth, Storage, and Studio. Each one is a process you must keep alive and upgrade.
Concile is one process. Running docker compose up starts the engine, the database, and the dashboard. You can also run concile build to ship one executable. It runs on Cloudflare Workers too.
Where Supabase is ahead
- It is Postgres. You get decades of tooling, standard SQL, and 40-plus preinstalled extensions. There is no vendor query language.
- You get auto-generated REST and GraphQL APIs from your schema. You do not need to write code for a plain CRUD API.
- Search is built in. It has full-text search through tsvector and vector search through pgvector. Concile has neither yet.
- It is a hosted product in 16-plus regions with SOC 2 Type 2 compliance. It offers compute tiers up to 64 vCPU and 256 GB on a single published tier.
Where Concile is ahead
- Live queries are computed on the server. The client does not have to interpret row events.
- Authorization is code. It runs in the transaction and under the type checker.
- You run one process instead of a ring of services.
- You can use SQLite for zero config or Postgres when you want Postgres. The app code stays the same.
- Durable workflows with compensation and a durable offline outbox are built in.
- There are no connection caps or compute bills. Supabase caps realtime peak connections at 200 on Free and 500 on Pro and Team. Supabase charges $10 per additional 1,000 connections. It also bills compute hourly per project on top of the plan.
Moving from Supabase
There is no migration tool because the model changes. Functions replace PostgREST calls and RLS policies. Your data remains portable. Export it from Postgres. Define the same tables in schema.ts. Import the data with concile migrate import. Each RLS policy becomes an if statement in the function that reads or writes that table. This is usually shorter than the policy was.
When to pick Supabase
You want Postgres and its ecosystem as the center of the system. You want a hosted product with regions and compliance today. You need built-in search. You are comfortable writing and testing SQL policies.
When to pick Concile
You want every screen to update on its own. You do not want to write invalidation logic. You want authorization you can read and test as code. You want a backend you can run as one process anywhere.