concept
Local-First Software
Local-First Software
An architectural pattern where the local device is the source of truth, the server is a sync coordinator (not an authority), and the network exists only to exchange state when it’s available. Partition mode isn’t a degraded state — it’s the normal mode of operation.
The inversion
Most apps treat the server as canonical:
read/write → network → server → network → response
(critical path)
When the network is slow, the app is slow. When the network is gone, the app is broken.
Local-first flips this:
read/write → local DB (instant)
↓
sync layer (background, when network available)
↓
other devices / server replica
Every read and write hits a local database. No round trip. No spinner. Not fast — instant.
Why the architecture works
- The app works completely offline because there’s no difference between offline and “normal.”
- When devices reconnect, crdt|CRDT-based sync handles the diverged state in the background.
- Recovery becomes routine infrastructure, not an incident.
The sync protocol that handles diverged state when devices reconnect is exactly the partition-recovery problem cap-theorem|Brewer's 2012 CAP paper described — but now solved by purpose-built tools rather than ad-hoc retry logic.
Tooling
- yjs — collaborative-editing-centric CRDT, dominant for rich-text and editor use cases
- automerge — JSON-document CRDT, shipped to millions in GoodNotes
- Purpose-built sync engines — Replicache, Triplit, Jazz, PowerSync, Electric SQL — built specifically to make local-first practical for SaaS
Real apps you’ve used
- A notes app that works at 35,000 feet (Bear, Apple Notes, Linear’s offline behavior).
- Linear — issues are available when the WiFi drops; everything syncs when you land.
- Figma (canvas) — partially local-first; CRDT-influenced for conflict resolution. See crdt.
That “feels fast” UX is partition recovery built into the architecture from the start, not a pleasant UX feature retrofitted on top of REST.
When to pick it
- Apps where users expect “instant” — notes, todos, design tools, code editors.
- Apps where offline use is real (mobile, travel, conferences, hospitals, fieldwork).
- Apps where collaboration is multi-device for the same user (not just multi-user).
When not to pick it
- Anything with strong global invariants — “balance never goes negative,” “username is unique,” “inventory count is accurate.” These need saga-pattern|sagas or coordinator-mediated writes; local-first doesn’t help.
- High-write-rate analytics/event streams — local-first’s value is interactive responsiveness, not throughput.
See also
- cap-theorem — local-first is the answer to “what if partition mode is the default state?”
- crdt — the sync layer
- partition-mode-design — generalizes the design pattern local-first specializes
- yjs, automerge, egwalker — tooling