The best backends for local-first apps

InstantDB is the easiest local-first backend to start with, optimistic writes, offline support and realtime sync in one product. ElectricSQL is the pick when the source of truth must stay Postgres. Triplit and Zero are strong for query-driven sync, and Convex covers realtime without full offline.

Editorial judgement last reviewed

Which backend is best for building a local-first app?

Local-first means the application reads and writes a local copy of its data and syncs in the background. Interactions are instant because nothing waits on a network round trip, the app keeps working on a train, and conflicts resolve rather than fail.

It is also genuinely hard. You need a local store, a sync protocol, conflict resolution, partial replication so a client doesn't download the entire database, and an authorisation model that works when the client holds real data rather than requesting it. Every product in this category is an attempt to make that tractable, and they make different trades.

The comparison below draws on our ConvexConvex logo alternatives hub, which scores local-first sync, optimistic updates, reactivity model and exit cost across eleven reactive backends.

How we ranked these

We ranked on how much of the hard part each product actually removes.

Offline capability. Does the app work with no network, and do writes queue and replay? Some products in this space are realtime-but-online-only, which is a different thing wearing similar words.

Conflict resolution. What happens when two clients edit the same record offline. CRDT-based, last-write-wins, or your problem.

Partial replication. Whether a client can sync a defined subset of data, which is the difference between a demo and a production app with real data volumes.

Authorisation. How access rules are enforced when the client holds data locally, the hardest unsolved problem in this category.

Source of truth. Whether your data lives in PostgresPostgreSQL logo you control or in the vendor's store, which determines exit cost.

The picks, ranked

  1. InstantDB logo

    InstantDB

    Easiest to start with

    The most approachable entry point to local-first. Optimistic writes, offline support, realtime sync and a relational-ish query model in one product, with a client API that feels like using a local database rather than orchestrating a sync engine.

    Queries are reactive by default and results update as data changes anywhere. Writes apply locally first and reconcile behind the scenes, so the UI never waits. For a collaborative app, documents, boards, anything multiplayer, you get most of the hard part for free.

    The trade is that your data lives in InstantDBInstantDB logo's store rather than a PostgresPostgreSQL logo you control, so exit cost is real. It's a young product with a small team, which cuts both ways: fast iteration, less operational history.

    Start here if local-first is the goal and you don't have a PostgresPostgreSQL logo requirement.

  2. ElectricSQL logo

    ElectricSQL

    Best when Postgres is the source of truth

    A sync layer over your existing PostgresPostgreSQL logo rather than a new database. Electric streams filtered subsets, shapes, of PostgresPostgreSQL logo data to clients and keeps them current. Your source of truth stays a database you own, host wherever you like, and can query with every tool that speaks SQL.

    That framing is the reason to choose it. You get local-first reads without giving up PostgresPostgreSQL logo, and if Electric disappeared tomorrow your data is untouched, you'd lose the sync layer, not the system of record.

    More assembly required than the all-in-one options. You provide the PostgresPostgreSQL logo, you define the shapes, and the write path is more explicit than a product that owns both ends. In exchange, exit cost is close to the floor for this category.

  3. Triplit

    Best query-driven sync

    A full-stack database with a client-side cache and a relational query model, built so the same queries run locally and on the server. Offline support and optimistic updates are first-class, and the schema is defined once in TypeScript with end-to-end types.

    The distinguishing idea is that subscriptions are queries rather than table listeners, so a client subscribes to exactly the data a screen needs and the sync engine maintains it. That's the right abstraction for partial replication, which is where naive local-first designs fall over once real data volumes arrive.

    Open source with a self-host path. Smaller ecosystem than the leaders, so budget time for the edges.

  4. Zero logo

    Zero

    Most sophisticated sync engine

    From the team behind Replicache, and the most technically ambitious sync engine in this roster. Zero's model is that you write queries and it handles synchronisation, caching and consistency, including partial replication with server-side authorisation, which is the problem most local-first systems handwave.

    Where it shines is applications with large datasets where each client needs a small, dynamic slice. The query-driven sync means the client pulls what the UI needs and nothing else, without you designing a replication strategy by hand.

    Newer and less battle-tested than the alternatives, with a steeper conceptual learning curve. Worth the investment if your app's data model is genuinely too large to replicate wholesale.

  5. Convex logo

    Convex

    Best realtime, if you don't need true offline

    Worth including because a lot of teams say local-first and mean instant and collaborative rather than works-on-a-plane. ConvexConvex logo delivers the former exceptionally well: every query is a live subscription, updates push automatically, optimistic updates are built in, and consistency is transactional per query.

    What it isn't is offline-first. There's no local database that keeps working with no network and replays writes on reconnect.

    If your users are always online and you want a realtime app without building a sync engine, ConvexConvex logo is the least work of anything on this page. If they genuinely go offline, you need one of the options above.

Be honest about whether you need offline

Local-first is fashionable, and a lot of teams adopt it for applications whose users have never been offline in their lives. The cost is real: sync bugs are among the hardest to reproduce and debug, conflict resolution introduces semantics your product team has to decide, and partial replication becomes a design constraint on every feature.

Ask what actually breaks without it. If the answer is "a spinner appears", you want a good realtime backend and an optimistic UI, not a sync engine. ConvexConvex logo, SupabaseSupabase logo or a normal API with TanStack Query will serve you well and cost far less complexity.

If the answer is "the user loses work", field tooling, mobile apps used in transit, note-taking, anything where a dropped connection means lost input, local-first is the correct architecture and worth the complexity.

There's a middle case that catches people: apps that don't need offline but do need instant. Local-first is one way to get that, and an optimistic UI over a fast API is a much cheaper one. Try the cheap version first and measure whether it's actually slow.

Authorisation is the hard part nobody advertises

In a conventional architecture, the server decides what each request may see. In a local-first architecture, the client holds data, so the sync layer must decide what to send before the client asks for it, and must reject writes it shouldn't accept.

This is where products in this category differ most, and where the demos are least representative. A demo app has one user and no permissions. Your app has teams, roles, sharing, and rows that become visible when someone is added to a project.

Ask three questions of any candidate. How are read rules expressed, and are they enforced server-side rather than trusted from the client? What happens when a user's access is revoked, does data already on their device get removed, and how quickly? And can rules be expressed per row and per field, or only per collection?

Then design your schema so permission boundaries align with sync boundaries. If a client syncs a workspace, make the workspace the unit of permission. Fighting that alignment later means either over-syncing data users shouldn't have or writing filtering logic in two places, and both are the kind of mistake you find out about in a security review.

Frequently asked questions

Is Convex local-first?

No. It's realtime and reactive with built-in optimistic updates, which covers instant and collaborative, but there's no local database that keeps working with no network and replays writes on reconnect. For genuine offline you need InstantDBInstantDB logo, ElectricSQLElectricSQL logo, Triplit or Zero.

Can I make Supabase local-first?

Yes, by adding a sync layer, ElectricSQLElectricSQL logo or PowerSync are the usual choices. SupabaseSupabase logo Realtime alone streams row changes over a websocket; it has no local persistence, write queue or conflict resolution.

How do conflicts get resolved?

It varies, and you should check before committing. Some use CRDTs for automatic merging, some use last-write-wins, some hand you the conflict. For collaborative text, CRDTs are close to essential; for record editing, last-write-wins is often acceptable.

What about SQLite in the browser?

SQLiteSQLite logo compiled to WebAssembly with OPFS storage is a solid local store, and several products here use it underneath. Building on it directly means writing the sync protocol yourself, which is the part these products exist to provide.