Lark vs Supabase: which should you use to replace Firebase Realtime Database?
Last updated: November 2026
Supabase is an open-source backend platform built on Postgres: SQL tables, row-level security, authentication, file storage, and edge functions, with a realtime layer on top. Lark is an alternative to the Firebase Realtime Database, and is wire-compatible with it. Choose Supabase if you're building a relational app and want a full Postgres backend. Choose Lark if you want to keep an existing Firebase Realtime Database app running without a rewrite, or if your workload is built around a live JSON tree.
Whenever someone asks for an open-source alternative to Firebase, Supabase is almost always the first name that comes up, and for good reason. I like Supabase quite a lot. If you're starting a new project and you want Postgres, authentication, storage, and serverless functions under one roof that you can host yourself, it's a great piece of engineering.
Where people get tripped up is that "Firebase" is twenty different products under one brand name, and the Firebase Realtime Database (RTDB) is a very specific beast. When a developer with an existing RTDB app hears "just switch to Supabase," what sounds like a database swap is actually a ground-up rewrite of their data model, client code, and permission system.
Both projects are open source, and both can get you off Google's servers, but they solve fundamentally different problems. Here's how they compare so you can figure out which one fits what you're building.
What's the core difference between Lark and Supabase?
The difference comes down to two things: data model and scope.
Supabase is a relational backend built around PostgreSQL. Your data lives in tables with columns, types, foreign keys, and migrations. You query it through PostgREST (which turns your schema into a REST/client API) or SQL, and Supabase bundles that database with GoTrue for authentication, an object storage service, edge functions, and an Elixir-based Realtime server.
Lark is a purpose-built JSON tree database that speaks the Firebase Realtime Database wire protocol. There are no tables, schemas, or SQL migrations. The entire database is a single JSON tree addressed by paths like /rooms/42/players/alice, and clients subscribe directly to paths to keep a local view in sync with the server.
Just as importantly, Lark is narrow on purpose. It only replaces the Realtime Database. It doesn't bundle its own user management system, file storage, or serverless functions, because it's designed to drop directly into an existing Firebase setup while you keep Firebase Auth, Hosting, and Storage (or pair it with whatever stack you already run).
How does realtime work in each?
Because the underlying databases are so different, "realtime" means something different in each system.
In Supabase, Realtime is a separate service sitting beside Postgres that gives you three distinct features. The first is Broadcast, which handles ephemeral pub/sub messaging between connected clients over WebSockets (useful for cursors or chat events that don't touch the database). The second is Presence, an in-memory CRDT state tracker that lets clients see who else is currently in a channel. The third is Postgres Changes, which listens to Postgres's logical replication stream (the WAL) and pushes inserts, updates, and deletes to subscribed clients after checking Row-Level Security (RLS) policies.
One practical detail worth knowing about Postgres Changes is how it scales with subscribers. When a row changes in a table with RLS enabled, Supabase has to check whether each subscribed user is allowed to see that row. Supabase's own documentation notes that Postgres Changes are processed on a single thread and that compute scales with the number of subscribers times the rate of writes, which is why they recommend using Broadcast triggers or separate public tables for high-fan-out workloads.
In Lark, the database is the realtime layer. Every write mutates an in-memory copy-on-write JSON tree owned by a single pinned CPU core, appends to a write-ahead log, and immediately broadcasts delta events (put and patch) to subscribed views on that same core. When a thousand clients subscribe to /rooms/42, Lark maintains a shared view on the server rather than re-running a database query a thousand times per write.
Lark also supports Firebase's onDisconnect primitives (so the server can automatically clean up a user's state the moment their socket drops) and adds volatile paths for high-frequency data like 20Hz player positions or mouse cursors. Volatile writes use the exact same path-and-rules model as the rest of your database, but the server batches them in memory without touching disk.
What does migrating an RTDB app to Supabase actually involve?
If you have an existing application running on the Firebase Realtime Database today, moving to Supabase is a full application rewrite. In practice, that project breaks down into four jobs:
First, you have to redesign your JSON tree into normalized SQL tables. Patterns that are natural in RTDB -- like deeply nested maps, dynamic keys, or denormalized fan-out paths -- have to be flattened into tables, join tables, and foreign keys, and you need a script to transform and load your exported JSON into Postgres. (While there are community tools for migrating Firebase Auth and flat Firestore collections to Supabase, every RTDB tree is structured differently, so the data migration is almost always bespoke.)
Second, you have to rewrite every data call in your frontend and backend. Every ref(), onValue(), onChildAdded(), set(), update(), push(), and runTransaction() call against the Firebase SDK gets replaced with @supabase/supabase-js queries (supabase.from('...').select()) and channel subscriptions (supabase.channel('...').on(...)). Unlike RTDB's live DataSnapshot views, Supabase's Postgres Changes sends individual row events, so your client code has to merge those events into local state itself.
Third, you have to rewrite your rules.json security rules from scratch as Postgres Row-Level Security policies in SQL.
Fourth, because Supabase's RLS policies are tightly integrated with Supabase Auth (auth.uid()), you generally either migrate your users over to Supabase Auth or set up third-party Firebase Auth integration inside Supabase.
Moving that same app to Lark looks completely different: you export your JSON from Firebase, import it into Lark, paste your existing rules.json into Lark's rules editor, enter your Firebase Project ID so Lark can validate your existing Firebase Auth tokens, and change the databaseURL string in your Firebase config. Your application code stays untouched.
Security rules vs. row-level security
To make the permission difference concrete, here is what the same rule -- "anyone signed in can read profiles, and users can only write their own profile" -- looks like in both systems.
In Firebase RTDB and Lark, permissions follow the shape of your JSON path tree and are written as Javascript-like expressions inside rules.json:
{
"rules": {
"profiles": {
"$uid": {
".read": "auth != null",
".write": "auth != null && auth.uid === $uid",
"displayName": {
".validate": "newData.isString() && newData.val().length <= 50"
}
}
}
}
}
In Supabase, permissions live on your Postgres tables as SQL Row-Level Security policies and column constraints:
create table public.profiles (
id uuid primary key references auth.users(id),
display_name text check (char_length(display_name) <= 50)
);
alter table public.profiles enable row level security;
create policy "Signed-in users can read profiles"
on public.profiles for select
to authenticated
using (true);
create policy "Users can insert and update their own profile"
on public.profiles for all
to authenticated
using (auth.uid() = id)
with check (auth.uid() = id);
Both models work well once you're used to them. Postgres RLS is much more expressive when permissions depend on relational joins across several tables. Firebase and Lark rules are much faster to iterate on when your data is a hierarchy of paths and you don't want to run DDL migrations every time you add a field. And if you already have a working rules.json file, Lark runs it as-is.
Pricing models compared
Both projects can be self-hosted for free, and both offer managed cloud hosting, but their cloud pricing models are shaped around different things.
Lark Cloud uses the same two-meter model as Firebase RTDB (storage and outbound bandwidth), at roughly half of Firebase's rates. The base plan is $10/month, which includes 2 GB of storage and 20 GB of outbound bandwidth. Past that, storage is $2.50/GB-month and outbound bandwidth is $0.50/GB (with volatile bandwidth billed at 1/5th the rate, or $0.10/GB). Inbound writes are free, there are no per-operation charges, and concurrent connections are a plan ceiling (up to 200k per database) rather than a metered line item.
Supabase uses tiered platform plans (a restricted Free tier, a Pro plan starting at $25/month, Team at $599/month, and Enterprise) combined with usage meters across several dimensions: dedicated Postgres compute instance size (which you scale up as your database grows), disk size, outbound egress, monthly active auth users, and specific quotas for Realtime (concurrent peak connections and millions of realtime messages sent).
Which one costs less depends on your workload. If you're building a standard CRUD application with modest traffic that fits inside Supabase's base Pro quotas, it's likely both Supabase and Lark's base level plan will have you covered. If you're running a realtime-heavy application that pushes tens or hundreds of millions of small state updates to connected clients, metering by message count and scaling Postgres compute for RLS checks can add up quickly, whereas Lark's delta batching and $0.10/GB volatile rate are built specifically for that traffic pattern.
Self-hosting each
If your main goal in leaving Firebase is to run your stack on your own servers, the operational footprint of the two projects is quite different.
Because Supabase is an entire backend suite, self-hosting it means running a multi-container Docker Compose stack of around a dozen services: PostgreSQL, Kong (API gateway), GoTrue (auth), PostgREST (REST API), Realtime (Elixir), Storage, imgproxy, Postgres-meta, Studio (the dashboard), Analytics/Logflare, and Vector. It's all open source (primarily under the Apache 2.0 and MIT licenses) and well documented, but it is a lot of moving parts to upgrade, monitor, and back up.
Lark is just two binaries: lark-edge (the Go gateway that terminates TLS, validates tokens, and serves the embedded admin dashboard) and lark-server (the Rust database engine). You can bring the whole stack up locally with make up-release, deploy it to Fly.io with a single script, or run the two binaries directly under systemd on a Linux box with local NVMe storage. Backing up a database is copying its folder on disk.
Lark is licensed under the AGPL v3. As we note in our open-source announcement, talking to Lark over the network from your proprietary web, mobile, or game client does not trigger the AGPL on your application code -- it works the same way as connecting to a Redis or Postgres server. The AGPL only requires you to share source changes if you modify Lark itself and offer that modified server to users over a network.
When Supabase is the better choice
You should pick Supabase over Lark if:
- You are starting a new application whose data is naturally relational -- users, orders, invoices, inventory, or anything where SQL joins, foreign keys, and transactions across tables will save you headaches.
- You want a single open-source platform that replaces all of Firebase (database, auth, file storage, and serverless functions) at once.
- Your team thinks in SQL and wants access to the broader Postgres ecosystem, including extensions like
pgvectorfor embeddings or PostGIS for geospatial queries. - Your realtime needs are modest.
When Lark is the better choice
You should pick Lark over Supabase if:
- You already have a production Firebase Realtime Database application and want to cut your bill, improve latency, or self-host without spending months rewriting your client code, data model, and security rules.
- Your application revolves around live, deeply nested, or flexible JSON state -- collaborative whiteboards, multiplayer browser or mobile games, live document editors, or presence-heavy social apps.
- You need high-frequency updates (10Hz to 60Hz cursors, positions, or telemetry) over WebSockets or WebTransport without hitting per-message quotas or hammering a relational database's write-ahead log.
- You're happy with Firebase Auth, Hosting, and Cloud Storage (or your existing backend) and only want to replace the Realtime Database piece.
Can you use both together?
Yes, and for a lot of applications, pairing them is actually a cleaner architecture than forcing one database to do two opposite jobs.
Use Postgres (via Supabase or any managed Postgres host) for your relational system of record: user accounts, billing, permissions, and historical records that you want to run SQL analytics and joins against. Then use Lark for the live, ephemeral, or collaborative JSON state: active game rooms, live canvas documents, cursor positions, and presence trees.
Wiring authentication between the two is straightforward. Lark's edge gateway validates standard HS256 JWTs alongside Firebase Auth tokens, reading the user's identity from either the uid or sub claim. Since Supabase Auth issues standard JWTs with the user's UUID in sub, you can either mint a short-lived Lark token from a Supabase Edge Function or configure your project secret so clients authenticated with Supabase can connect straight to Lark and have their user ID show up as auth.uid in your Lark security rules.
Side-by-side summary
| Feature | Lark | Supabase |
|---|---|---|
| Data model | Single JSON tree per database | Relational SQL tables (PostgreSQL) |
| Firebase RTDB wire-compatible | Yes (official Firebase SDKs work) | No (requires rewriting against supabase-js) |
Existing RTDB rules.json works |
Yes | No (rewrite as SQL Row-Level Security) |
| Realtime model | Path subscriptions, deltas, onDisconnect, volatile paths |
Broadcast, Presence, Postgres Changes (WAL) |
| High-frequency / UDP support | Native volatile batching + WebTransport (QUIC) | WebSockets only (Broadcast recommended) |
| Authentication | Validates Firebase Auth + custom HS256 JWTs | Built-in Auth service (GoTrue) |
| File storage & serverless functions | No (keep Firebase's or bring your own) | Built-in Storage and Edge Functions |
| Self-hosting footprint | 2 services (lark-edge + lark-server) |
~10–12 services in Docker Compose |
| Open-source license | AGPL v3 | Apache 2.0 / MIT |
| Cloud pricing shape | $10/mo base + per-GB storage & egress | Tiered plans ($25/mo Pro) + compute + message/connection quotas |
Frequently asked questions
Is Supabase a drop-in replacement for the Firebase Realtime Database?
No. Supabase is an open-source alternative to the broader Firebase platform, built on Postgres. It does not speak the Firebase Realtime Database wire protocol or run Firebase security rules, so migrating an existing RTDB app to Supabase requires redesigning your data into SQL tables and rewriting your client data layer.
Can I move from Lark to Supabase later if my needs change?
Yes. Your data in Lark is plain JSON that you can export at any time from the dashboard or the REST API. Moving from Firebase RTDB to Lark takes a few minutes and doesn't lock you into anything new.
Which one has lower latency for realtime updates?
We haven't run a head-to-head benchmark against Supabase's Elixir Realtime cluster, so we won't make claims about their numbers. On Lark's side, because the JSON tree lives in memory on a thread-per-core Rust engine with no garbage collector and no cross-process replication hop between the write and the subscriber fan-out, internal write-to-broadcast latency is under 10ms at p50 and under 50ms at p99.
Why doesn't Lark include built-in user management or file storage?
Because most teams migrating from Firebase RTDB are already using Firebase Auth and Cloud Storage (which are inexpensive and work well), or they already have an existing application backend. Focusing strictly on the realtime database lets us stay 100% wire-compatible with RTDB and keep the self-hosted server down to two lightweight binaries.
Firebase and Firebase Realtime Database are trademarks of Google LLC. Lark is an independent project and is not affiliated with, endorsed by, or sponsored by Google.