Supabase vs Convex - SQL Database or Reactive TypeScript?
Supabase vs Convex is a choice between two programming models. Supabase is Postgres: you design tables, query with SQL or a generated REST API, and protect rows with policies. Convex is a reactive database where your backend is TypeScript functions running inside it; queries re-run automatically and every client stays in sync without writing any subscription code. Pick Convex for highly interactive TypeScript apps where live updates are the product. Pick Supabase when you want SQL, standard Postgres tooling, reporting and an exit path to any Postgres host.
Neither is a drop-in replacement for the other. Moving between them means rewriting your data layer, so it's worth deciding carefully.
#The models side by side
| Supabase | Convex | |
|---|---|---|
| Database | Postgres | Document-relational (JSON-like documents, references by id) |
| Query language | SQL; REST and GraphQL generated from the schema | TypeScript query functions, no SQL |
| Writes | SQL, REST, RPC to Postgres functions | Mutation functions, each a transaction |
| Transactions | Postgres (READ COMMITTED default, SERIALIZABLE available) | Serializable with optimistic concurrency, automatic retries |
| Realtime | Subscribe to Postgres changes, broadcast, presence | Every query is live; clients update automatically |
| Side effects | Edge Functions (Deno) | Actions (can call external APIs) |
| Access control | Row Level Security | Checks in your functions |
| Self-hosting | Docker Compose | Open-source backend, FSL Apache 2.0 license |
#How Convex works
From Convex's docs: Convex is "the open source, reactive database where queries are TypeScript code running right in the database." There are three kinds of functions:
- Queries read data, can't make network requests, and are reactive: "Whenever any data on which a query depends changes, the query is rerun, and client subscriptions are updated."
- Mutations read and write; "the entire Convex mutation function is a transaction," with serializable isolation and automatic retries on conflict.
- Actions can call third-party APIs (an LLM, an e-mail service) and reach the database only through queries and mutations.
On the client, a React hook subscribes to a query and re-renders when the result changes. There's no cache to invalidate and no websocket code to write. That's Convex's big selling point, and it's real.
#How Supabase works
You define tables in SQL and get APIs from the schema:
create table public.messages (
id bigint generated always as identity primary key,
room_id bigint not null,
author_id uuid not null default auth.uid() references auth.users,
body text not null,
created_at timestamptz default now()
);
alter table public.messages enable row level security;
create policy "Room members read" on public.messages for select to authenticated
using (room_id in (select room_id from public.room_members where user_id = auth.uid()));Reading and listening on the client:
const { data } = await supabase
.from('messages').select('*').eq('room_id', 42).order('created_at')
supabase.channel('room-42')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'messages', filter: 'room_id=eq.42' },
(p) => append(p.new))
.subscribe()More code than Convex for the live part. In exchange, the same table works with any SQL client, BI tool, ORM or pg_dump.
#Where each model shines
Convex is a strong fit for:
- Collaborative apps (whiteboards, docs, multiplayer games) where everything on screen must stay live.
- Teams that are TypeScript end to end and don't want to context-switch to SQL.
- Apps whose logic is mostly "on this event, update these documents", which fits mutations well.
Supabase is a strong fit for:
- Relational data with reporting needs: "revenue by plan by month" is one SQL query.
- Apps that need Postgres extensions: pgvector, PostGIS, full-text search, cron.
- Teams that want the database usable from many tools and languages.
- Anyone who wants to be able to take the database to another host.
#Security model
In Convex you check permissions inside each function, for example by reading the user's identity and verifying they belong to a room. It's ordinary code, easy to read and test.
In Supabase, policies live in the database and apply to every API path. One policy protects REST, GraphQL, Realtime and any future client. The risk is the inverse: forgetting to enable RLS on a new table leaves it open, so check the security advisor.
#Pricing, as of November 2026
Convex (pricing):
| Free & Starter | Professional | |
|---|---|---|
| Price | $0, pay as you go | $25 per developer/month |
| Function calls | 1M included, then $2.20 per 1M | 25M included, then $2 per 1M |
| Database storage | 0.5 GB, then $0.22/GB | 50 GB, then $0.20/GB |
| Bandwidth | 1 GB, then $0.132/GB | 50 GB, then $0.12/GB |
| File storage | 1 GB | 100 GB |
Supabase (pricing): Free with 500 MB database, 1 GB storage, 5 GB egress, 50,000 MAU, 2 active projects, paused after a week of inactivity. Pro from $25/month per organization (not per developer) with 8 GB disk, 100 GB storage, 250 GB egress and 100,000 MAU.
The key difference: Convex's paid plan scales with the number of developers; Supabase's with resources and projects. A team of four on Convex Professional is $100/month before usage. A team of four on Supabase Pro is $25 plus compute.
Also note Convex counts function calls. Reactive queries re-run when data changes, so a busy collaborative screen with many subscribers can use a lot of calls. Model it with your real traffic.
#Lock-in and exit paths
Convex's backend is open source under the FSL Apache 2.0 license, which converts each release to Apache 2.0 after two years, and it can be self-hosted (self-hosting). Your code, however, is written against Convex's function model; moving to another database is a rewrite.
Supabase data is standard Postgres. Moving to another Postgres host is a dump and restore, and moving to another Supabase-compatible platform keeps your client code too.
#Where StitchDB fits
StitchDB is a hosted Postgres backend that speaks the Supabase APIs, so the Supabase side of this comparison applies to it as well (compatibility). Two of its features narrow the gap with Convex's developer experience:
- Offline sync:
stitchdb.offline({ tables: ['todos'] })keeps tables on the device,subscribe()re-renders on changes, and writes queue offline with a conflict rule per table. - Collaborative documents and realtime message history, so reconnecting clients get missed broadcasts in order.
const db = stitchdb.offline({ tables: ['todos'] })
await db.ready
const stop = db.table('todos').subscribe((rows) => render(rows))It's priced per account, not per developer: Pro is $15.99/month with 10 team members. The trade-offs: EU-only hosting (Germany and Finland), a younger platform, no self-hosted edition, and it's still SQL and policies at heart, not Convex's all-TypeScript model.
#Who should pick what
- Pick Convex if live, collaborative UI is the core of your product and your team prefers TypeScript to SQL.
- Pick Supabase if your data is relational, you need SQL and extensions, and you want a portable database with worldwide regions.
- Pick StitchDB if you want the Supabase model hosted in the EU with built-in offline sync and per-account pricing.
More comparisons: Convex alternatives and the best backend as a service platforms.
#FAQ
#Is Convex better than Supabase for realtime?
For automatic live queries, yes: every Convex query is reactive by default. Supabase gives you change streams you subscribe to and handle yourself.
#Can I use SQL with Convex?
No. Convex queries are TypeScript functions. Its docs say there is no SQL to write.
#Is Convex open source?
The backend is open source under the FSL Apache 2.0 license and can be self-hosted.
#Which is cheaper for a team?
Supabase Pro is priced per organization ($25/month base); Convex Professional is $25 per developer per month, as of November 2026.
Want Postgres with live, offline-ready tables? Try StitchDB free.