CRDTs merge concurrent edits without a central lock. Build an offline-first app with Automerge, IndexedDB, and sync in three steps. Read now.
Why CRDTs fit offline-first work
Offline-first apps let people keep writing, editing, and organizing data when the network is gone. The hard part is not storing data locally—it is reconciling two devices that both changed the same document while apart. A last-write-wins approach discards work. A central lock forces everything through a single authority, which offline clients cannot reach. CRDTs (Conflict-free Replicated Data Types) solve this by design: concurrent edits merge into a consistent result without a lock and without choosing a single “winner” by timestamp alone.
A CRDT encodes both the value and enough history (or metadata) so that two replicas can exchange their states and end up identical. Order of delivery does not matter as long as both sides eventually see the same set of operations. That property is what makes offline sync reliable instead of ad hoc.
What you need on the client
In the browser, a practical stack pairs a CRDT document library with durable local storage and a thin sync layer. Automerge gives you a document model that supports concurrent text and structured edits and produces mergeable changes. IndexedDB holds the document (or its change log) so a refresh or a cold start does not lose offline work. Sync is the bridge: when the network returns, the client sends local changes and applies remote ones, relying on the CRDT merge rather than custom conflict UI for every field.
You do not need a special “offline mode” product surface. You need a single code path that always reads and writes the local CRDT document, and a background job that exchanges changes when connectivity allows. The UI stays simple because the source of truth on the device is already mergeable.
Three steps to a working sync loop
- Step 1 — Model the document with Automerge. Represent your app state as a CRDT document (maps, lists, text). Apply every user edit as a local change. Keep the document identity stable so peers refer to the same logical record.
- Step 2 — Persist with IndexedDB. After each change (or on a short debounce), write the document binary or change set to IndexedDB. On load, restore from IndexedDB first; only then start the network. That order guarantees offline sessions survive restarts.
- Step 3 — Sync when online. Exchange changes with a peer or backend that stores the same Automerge document. Apply remote changes into the local document; Automerge merges concurrent edits. Broadcast local changes you have not yet sent. Retry with backoff when the connection drops.
Keep the server dumb if you can: store blobs of CRDT state or append-only change logs, and let clients merge. If you must enforce permissions, do that at the transport layer (who may read or write which document), not by rewriting merged field values on the server.
Tradeoffs and practical guidance
CRDTs are not free. Documents grow with metadata; long-lived text can bloat if you never compact or snapshot. Concurrent list edits can produce orderings that feel surprising if you expected a human editor’s intent rather than a mathematical merge. Some domains still need product-level rules—for example, “only one assignee”—which you implement as application constraints on top of the CRDT, not as a replacement for it.
Start with one shared document type (a note, a checklist, a canvas object graph). Prove the three-step loop: edit offline, kill the tab, reopen, sync with a second device, confirm both converge. Add auth, multi-document indexes, and compaction only after that loop is boringly reliable. Offline-first succeeds when merge is automatic and local durability is non-negotiable—not when you invent more conflict dialogs.