Local-First, State of the Art
Everything you need to get caught up on local-first software — the theory, the sync-engine landscape, the hard unsolved parts, and how to actually pick a stack for a web or mobile app.
01What local-first actually means
The term comes from Ink & Switch's 2019 essay Local-First Software (and Kleppmann et al.'s accompanying paper). The core inversion: the primary copy of your data lives on the user's device, and the server — if there is one — is a sync peer, not the source of truth. The essay defines seven ideals: instant response, multi-device, offline, collaboration, longevity ("your data outlives the app"), privacy, and user control.
It's worth separating three things that get conflated:
- Offline-first — a cache-and-queue strategy for cloud apps. The server still owns the data. (Trello works this way.)
- Local-first — the device owns the data; sync is a replication problem between equals. (Linear, Actual, Anytype.)
- The pragmatic middle — most commercial "local-first" apps in 2026: a full local replica with optimistic writes, but a server that remains authoritative for permissions and arbitration. This is where sync engines live, and it's where most of the recent energy is.
Why should an advanced engineer care beyond the ideology? Two reasons that show up over and over in the source material. First, performance: reading from a local store means every interaction is a sub-millisecond query, which is how Linear and Superhuman (the 100 ms rule) feel the way they do. Second, architecture simplification: once a sync engine owns data movement, you delete the entire fetch/cache/invalidate/loading-spinner layer of a conventional app — the argument made in Are Sync Engines the Future of Web Applications? and Riffle's reactive-relational essay.
For balance, read Why Haven't Local-First Apps Taken Off? (2025): the honest answer is that you're taking on distributed-systems complexity (migrations, conflicts, partial replication, auth) that the cloud model centralizes away, and until recently the tooling made you pay that cost yourself. The tooling is what changed — that's most of what this post covers.
02The architecture spectrum
Every local-first system answers the same four questions: where does data live locally, how do writes propagate, who resolves conflicts, and who enforces permissions? The answers place you on a spectrum:
Moving right buys you autonomy and resilience; it costs you central control, easy auth, and simple schema evolution. The single most useful framing in the whole reading list is from You Might Not Need a CRDT: if you have a server anyway, let it be the arbiter and your data structures get radically simpler. Figma famously runs on this principle — per-property last-writer-wins arbitrated by the document server, not a CRDT (How Figma's Multiplayer Works).
Most production systems today sit in the second column, borrow CRDT techniques where cheap (see fractional indexing, below), and reserve full CRDTs for text.
03Conflict resolution: CRDTs, OT, and neither
When two offline devices edit the same data, something must merge the results. Three schools:
Operational Transformation (OT)
The Google Docs approach: transform concurrent operations against each other, usually requiring a central server to sequence them. Mature but notoriously hard to implement correctly — play with the interactive OT visualization to see why. Joseph Gentle, who built OT systems at Google Wave, wrote the definitive conversion story: I Was Wrong. CRDTs Are the Future.
CRDTs
Conflict-free Replicated Data Types: data structures whose merge is commutative, associative, and idempotent — replicas converge no matter what order updates arrive in, no central sequencer required. Start with A Gentle Introduction to CRDTs, then Jake Lazaroff's interactive intro (build a LWW register in ~100 lines), then Matt Weidner's Designing Data Structures for Collaborative Apps for how to think in CRDT primitives. For depth, Bartosz Sypytkowski's 22-post series is the long course.
Two objections have historically kept CRDTs out of production, and both are now largely answered:
- "They're slow and memory-hungry." CRDTs Go Brrr documents a 5000× speedup over a naive implementation; Kevin Jahns' benchmarks show Yjs handling huge documents fine; Automerge 3 cut memory ~10×. Modern engines (Yjs, Loro, Diamond Types, json-joy) are Rust/WASM-fast.
- "Rich text and lists interleave badly." Solved-ish: Peritext (rich-text CRDT), Kleppmann's CRDTs: The Hard Parts covers move operations and interleaving. See mu-txt for a shipping Peritext-based editor built on json-joy.
Server reconciliation (neither)
The pragmatic third way: clients send intents (mutations), the server applies them in order against authoritative state, clients rebase their optimistic state on the result. This is Figma's model, Linear's model, and the model of Replicache/Zero-style engines. You lose peer-to-peer merges; you gain centralized validation, permissions, and dramatically simpler reasoning.
Rule of thumb distilled from the list: collaborative free-form text → CRDT (Yjs/Loro/Automerge). Structured app data with a server → server reconciliation or a sync engine. True P2P/E2EE requirement → CRDT, because no server can arbitrate what it can't read. James Long's CRDTs for Mortals (with a full reference app) shows the hybrid: plain SQLite + per-column LWW timestamps — the architecture behind Actual Budget.
04The sync-engine landscape
This is where the field moved fastest in 2024–2026. The players cluster into four families:
Postgres-replication engines — keep your backend, sync it down
| Engine | Model | Notes |
|---|---|---|
| ElectricSQL | Partial replication of Postgres via "shapes" over HTTP | Read-path sync engine; writes go through your API. Pairs with PGlite (Postgres-in-WASM) or TanStack DB on the client. |
| PowerSync | Postgres/MongoDB/MySQL → local SQLite, dynamic sync rules | Strongest mobile story (Flutter, React Native, Kotlin, Swift). Writes via upload queue to your backend. |
| Zero | Query-driven sync: client subscribes to ZQL queries, server maintains them incrementally | From the Replicache team (Replicache itself is in maintenance mode). Server reconciliation with custom mutators; probably the most-watched engine right now. |
Batteries-included platforms — Firebase, but local-first
| Platform | Model | Notes |
|---|---|---|
| InstantDB | Client-side triple store, relational queries (InstaQL), optimistic writes | Open-source, hosted or self-hosted; "a Firebase that syncs." |
| Triplit | Full-stack TypeScript sync engine + DB | Acquired by Supabase in 2025 — expect its ideas to surface there. |
| Jazz | CoValues: CRDT-based collaborative values with built-in auth, permissions, E2EE, sync, and blob storage | The most complete "delete your backend" framework; groups/accounts model handles the auth problem most CRDT stacks punt on. |
| LiveStore | Event-sourcing: append-only eventlog, materialized into in-memory SQLite, synced | From Johannes Schickling (Prisma founder). Redux-meets-SQLite; strong devtools, web + Expo. |
Client-side reactive databases — bring your own sync
| Library | Storage | Notes |
|---|---|---|
| RxDB | IndexedDB/OPFS/SQLite adapters | Mature, plugin-heavy; replication protocols for CouchDB, GraphQL, HTTP, WebRTC. Their why-local-first essay is a good sales pitch for the whole space. |
| TanStack DB | In-memory collections, differential dataflow | Reactive live queries + optimistic mutations over any sync backend (designed to pair with Electric). The "query layer" piece of the puzzle. |
| TinyBase | In-memory, pluggable persisters | Tiny, dependency-free reactive store with CRDT sync and rich devtools. |
| Dexie.js | IndexedDB | The veteran IndexedDB wrapper; Dexie Cloud adds sync. |
| Evolu | SQLite (WASM) | E2E-encrypted local-first SQLite with sync; type-safe, minimalist, privacy-absolutist. |
| Fireproof | Browser-native, content-addressed | Merkle-CRDT ledger DB; sync to any object store. |
| Verdant | IndexedDB | Storage + sync + realtime for small apps; built by one dev for his own products, pragmatic and well-documented. |
CRDT libraries — the raw material
| Library | Sweet spot | Notes |
|---|---|---|
| Yjs | Collaborative text/editors | The industry default; bindings for ProseMirror, CodeMirror, Monaco, tiptap. Servers: Hocuspocus, Y-Sweet, or hosted Liveblocks. |
| Automerge | JSON documents, versioned data | Ink & Switch's library; Rust core, v3 brought ~10× memory reduction. Best-in-class history/branching story. |
| Loro | JSON + rich text + movable trees | Newest generation; Rust, fast, time-travel built in. |
| json-joy | JSON + Peritext rich text | Performance-obsessed; powers mu-txt. |
Two cross-cutting comparisons are worth reading whole: The Spectrum of Local-First Libraries (Triplit vs Evolu vs Zero vs LiveStore, by DX) and Choosing a Sync Engine in 2026 (first-hand selection war story). Neon's framework comparison and Jared Forsyth's database series add rigor. An emerging thread to watch: Ossa, a 2025 attempt at an open universal sync protocol so apps aren't locked to one engine, and Braid, the IETF draft that would make HTTP itself a sync protocol.
05The local storage layer
Whatever engine you pick sits on one of these substrates:
- SQLite-in-WASM (web) — the big unlock of the last few years, via OPFS for persistence. Notion's WASM-SQLite writeup is the canonical case study (including the SharedWorker trick for multi-tab). SQLite-in-Vue guide for a hands-on start.
- Postgres-in-WASM — PGlite (~3 MB gzipped) gives you real Postgres with live queries in the browser. Pairs naturally with Electric.
- CRDT-native SQLite — cr-sqlite is a SQLite extension making tables multi-writer CRDTs ("Git for your data").
- Replicated SQLite as a service — libSQL/Turso embedded replicas: local reads, synced to edge-hosted SQLite.
- IndexedDB — still the compatibility floor; Dexie, RxDB, Verdant, and Fireproof build on it.
- Mobile-embedded — SQLite everywhere (PowerSync, WatermelonDB, op-sqlite/expo-sqlite); Couchbase Lite and ObjectBox for the enterprise/IoT end.
- Plain files — don't laugh: Obsidian and Logseq built empires on Markdown folders, and Tonsky's Local, First, Forever argues file-sync (Dropbox-style) plus a merge-friendly format is the most durable sync substrate of all.
06P2P & the networking layer
Most apps ship with a sync server, but the fully-decentralized end of the spectrum matured too:
- Iroh — Rust, QUIC-based dial-by-public-key connectivity with relay fallback; the current default answer for "I need P2P connections that actually connect."
- Hypercore/Hyperswarm and the Pear runtime — append-only logs, DHT discovery, zero-infrastructure desktop/mobile apps (the Keet stack).
- libp2p / IPFS / OrbitDB — the modular heavyweight stack.
- AT Protocol — self-authenticating data + portable identity; Jake Lazaroff argues it makes a solid sync-server foundation where users own the infrastructure. Nostr is the minimalist relay-based cousin.
- Earthstar — small-group, offline-first P2P sync designed for humans rather than protocols.
Also file under "infrastructure that made this easier": Cloudflare Durable Objects (a stateful, SQLite-backed object per document — the natural home for a sync/presence server) and PartyKit built on top of them.
07The hard parts
These are the areas where you'll spend your actual engineering budget, and where research is still active:
Auth & permissions without a trusted server
The unsolved-until-recently problem. If any device can write, who enforces "read-only collaborator"? Directions: UCAN (capability tokens built on DIDs — delegation works offline), and Ink & Switch's Beehive (convergent capabilities: access control that merges like a CRDT). Jazz ships a practical groups-based version today; most sync engines instead keep permissions on the server (Zero's queries, Electric's shapes, PowerSync's sync rules).
End-to-end encryption
CRDTs merge on any replica, so they can merge on devices — the server can be a blind relay. Excalidraw's E2EE writeup is the approachable intro; Kerkour's CRDT+E2EE research notes covers the sharp edges; for group key management the standard is now MLS (RFC 9420) with OpenMLS as the Rust implementation. Shipping examples: Jazz, Evolu, Anytype, Standard Notes, Notesnook.
Schema migration
Old clients holding old data must interoperate with new ones — you can't run a Rails migration on someone's phone. Ink & Switch's Project Cambria (bidirectional lenses) is the research answer; in practice engines handle it with additive-only schemas, version-gated sync, or per-document versioning. The CTO's guide covers pragmatic strategies. Ask about this before adopting any engine.
Partial sync at scale
You can't replicate a 10 GB workspace to a phone. Every serious engine has a partiality mechanism — Electric's shapes, Zero's synced queries, PowerSync's sync rules — and Linear's scaling story is the best account of what happens when you get this wrong and have to re-architect live.
Version control for everything
The research frontier: Upwelling (private drafts + real-time collab) and Patchwork (branch/diff/merge for arbitrary apps) point at Git-like workflows over CRDT history — Automerge and Loro already expose the primitives.
08Who runs this in production
09Choosing a stack in 2026
The decision tree, distilled from the comparison posts and case studies above. Start from your constraint, not from a library:
| Your situation | Reach for | Why |
|---|---|---|
| Existing Postgres backend, want local-first reads | ElectricSQL + PGlite/TanStack DB | Read-path sync without surrendering your write path or API. |
| Web app, relational data, real-time multiplayer | Zero, or InstantDB | Query-driven sync + server-reconciled writes; permissions stay server-side. |
| Mobile app (RN/Flutter/native), existing backend | PowerSync | Local SQLite, mature mobile SDKs, backend-agnostic writes. (See also Expo's local-first guide.) |
| Mobile, no backend to keep | WatermelonDB, LiveStore (Expo), or Couchbase Lite | On-device-first reactive DBs with sync options. |
| Greenfield, want zero backend code | Jazz, or Triplit-style platform | Auth + permissions + E2EE + sync in one model; accept framework lock-in. |
| Collaborative text/canvas editor | Yjs (+ Hocuspocus/Y-Sweet/Liveblocks), or Loro/Automerge | This is the one domain where CRDTs are unambiguously the answer. |
| Privacy-absolutist / E2EE required | Evolu, Jazz, or Automerge + your own blind relay | Server can't arbitrate what it can't read — you need mergeable data. |
| No servers, ever | Automerge/Loro over Iroh, or Pear runtime | The full-decentralization stack, now actually practical. |
| Event-sourced state, auditability, devtools | LiveStore | Eventlog as source of truth, SQLite as a derived view. |
And the meta-advice, which nearly every practitioner post converges on:
- Decide who arbitrates. Server-reconciled or CRDT-merged is the fork in the road; everything else follows. Default to a server if you have one (you might not need a CRDT).
- Model mutations as intents, not state patches — it's what makes optimistic UI, undo, and server validation composable. (Zero's custom mutators, LiveStore events, Actual's messages all encode this.)
- Plan partial sync and migrations on day one. These are the two things you cannot bolt on later — Linear re-architected twice.
- Steal fractional indexing for anything ordered.
- Prototype the sync failure modes early — two devices offline for a week, clock skew, a tombstoned entity edited elsewhere. Superhuman's unreliable-networks post is the checklist.
10Staying current
The field moves monthly. The high-signal feeds:
- localfirstweb.dev — community hub, with monthly online meetups
- Local-First News — weekly newsletter (releases, talks, meetups)
- localfirst.fm — the podcast; the Maggie Appleton episode on home-cooked software pairs well with the AI moment
- Local-First Discord — where the library authors hang out
- Local-First Conf and SyncConf — the conference circuit
- crdt.tech and awesome-crdt — the theory rabbit hole
If you read only five things from this post: the original essay, You Might Not Need a CRDT, Linear's scaling story, The Spectrum of Local-First Libraries, and Choosing a Sync Engine in 2026. That's the theory, the counterweight, the production reality, and the shopping guide — enough to make a defensible architecture call.