You're starting a new app in 2026 and the backend choice keeps narrowing to two names: Convex and Supabase. Both let you skip writing a REST layer. Both ship a TypeScript client, built-in auth, file storage, and a free tier you can launch on. But they disagree about something fundamental — what a backend is supposed to do for you. We built small apps on each to find where the line actually falls, and the answer is less about features than about one architectural decision that shapes everything else.
The core split: reactive functions vs. a Postgres you own
Supabase is a managed PostgreSQL database with services arranged around it: Auth, Storage, Edge Functions, and a Realtime engine that streams row changes over WebSockets. You model data in SQL, write Row Level Security (RLS) policies to control who reads and writes what, and query from the client through an auto-generated API. If you already know Postgres, you know most of Supabase on day one. The database underneath is a real Postgres instance — you can connect with psql, run migrations with any tool you like, add extensions, and pg_dump the whole thing whenever you want.
Convex removes the SQL layer entirely. You write queries and mutations as TypeScript functions that run on Convex's servers. The headline feature is reactivity: Convex tracks exactly which documents each query reads, and when any of those documents change, it re-runs the query and pushes the new result to every subscribed client automatically. There's no "subscribe to this table" step and no client cache to invalidate — a useQuery hook in React stays live by default. Mutations run as ACID transactions, and the data model is document-relational rather than tables-and-joins.
That single choice cascades through everything. In Supabase, realtime is something you opt into per subscription, and you reason about cache invalidation yourself. In Convex, everything is reactive and you'd have to work to make it not be.
The authorization models differ as much as the data models. Supabase pushes access control into the database with RLS policies written in SQL — powerful, but a known source of subtle bugs when a policy is too loose or too strict. Convex has no RLS; you enforce access inside your server functions in TypeScript, alongside the rest of your logic. Neither is strictly safer. RLS keeps the rule next to the data; function-level checks keep it next to the code path that needs it.
Where each one actually wins
Convex wins for live-by-default apps: collaborative editors, dashboards that must reflect the latest write, multiplayer features, chat, anything where stale data on screen is a bug. The end-to-end TypeScript story is genuinely tight — your schema, server functions, and client share types with no separate codegen command you have to remember to run after every change. The result is noticeably less glue code for the class of apps it targets. If your product's whole point is that two people see the same state at the same time, Convex hands you that for free.
Supabase wins when you want a database you understand and can leave. SQL is a portable skill and Postgres is a portable artifact. The surrounding ecosystem is enormous: pgvector for embeddings, PostGIS for geospatial queries, every ORM, every BI and analytics tool, and the long tail of Postgres extensions. If your app leans more toward CRUD-and-reports than live collaboration, the reactivity Convex centers on is complexity you're carrying but not using — and a plain Supabase query plus an occasional realtime channel covers you with tools that have a decade of documentation behind them.
Don't pick based on a benchmark screenshot. The deciding question isn't raw throughput — both handle typical app loads fine. It's whether your app is fundamentally reactive (state changes that multiple clients must see immediately) or fundamentally transactional-with-reports (writes, reads, and the occasional live view). Choosing the wrong axis means fighting your backend's defaults for the life of the project.
Lock-in, migration, and cost
Both companies open-sourced their backends — Supabase as a self-hostable Docker stack, and Convex open-sourced its backend in 2024 so you can run it yourself. But "open source" and "easy to leave" are not the same claim. A Supabase exit is a pg_dump: your data lands in any Postgres on earth, and your queries are standard SQL. A Convex exit means rewriting your server functions and remapping the document-relational model onto whatever you migrate to, because the reactivity that saved you code lives in Convex's runtime, not in your data. The thing that makes Convex pleasant is also the thing you can't carry out the door.
On cost, both run a free tier that's enough to ship a side project or early MVP, with paid plans starting around $25/month and usage-based charges above that as you scale. At small scale the bill is comparable; at large scale your spend depends far more on your access patterns — how many reactive subscriptions Convex is fanning out, or how heavy your Postgres reads and bandwidth get on Supabase — than on the sticker price. Model your own workload before assuming one is cheaper.
For either stack, a TypeScript-aware editor pays for itself fast — Convex's function-based model and Supabase's generated types are both far easier to work with when your tooling understands the types end to end.
The honest summary: Convex if your app is reactive at its core and you want to write TypeScript instead of SQL and cache-invalidation logic. Supabase if you want a real Postgres database you can reason about, extend, and walk away from. Both are good. They're just answering different questions.
Originally published at pickuma.com. Subscribe to the RSS or follow @pickuma.bsky.social for new reviews.
Top comments (0)