Guide

A single-leader database never has write conflicts. Every write goes through one node, which puts them in order. But a single leader adds delay. Users in Sydney wait for every write to reach a leader in Virginia. A phone on a plane cannot write at all. Two people editing one document need to see each other's typing in tens of milliseconds.

Once more than one replica accepts writes, two of them can change the same data without knowing about each other. Something has to decide the result when they sync. This topic covers the options, from the simplest and most lossy to the designs that keep every change.

Concepts in this section

Read the pages in this order.

StepConceptWhat it answers
1Concurrent writes and last-write-winsWhat is a conflict, and why does the simplest rule lose data?
2CRDT countersHow do replicas merge counts without coordinating?
3OR-sets and add-winsHow do adds and removes merge without bringing deleted items back?
4Text editing: OT vs sequence CRDTsHow do two people's typing merge?
5Design a collaborative editorHow do the pieces fit together?

Where conflicts come from

A conflict appears whenever a replica accepts a write that another replica has not seen yet.

  • Multi-leader replication. Each region accepts writes and copies them to the others. Two users in different regions can edit one record within the replication lag.
  • Leaderless replication. In Dynamo-style stores, any replica accepts writes, so two writes to one key can be concurrent.
  • Offline clients. A phone that edits offline is a leader whose lag lasts hours or days.
  • Real-time collaboration. Clients apply their own edits at once, so concurrent edits are the normal case.

Strategies

StrategyWhat it doesCost
Last-write-winsKeeps the write with the highest timestampSilently drops concurrent writes, trusts clocks
Application mergeCode merges the versions, such as a cart unionMerges can resurrect deletes
SiblingsKeeps all concurrent versions for the reader to mergeEvery reader needs merge logic
CRDTsData types whose merges always convergeMetadata, and convergence is not always the answer users want
Server-ordered editsA server orders operations, as in Google Docs and FigmaEdits flow through the server

Siblings keep every concurrent value. In a Dynamo-style cart, the reader merges the siblings and writes back one value that covers both. A naive union can bring deleted items back, which is the problem OR-sets solve.

Local-first software

In 2019, Ink & Switch published "Local-first software". It argues that apps should keep the main copy of data on the user's device, work offline, sync in the background, and still support collaboration. CRDTs make that possible. Sync engines now give apps a local database that syncs automatically, and many of them use server-authoritative rules instead of full CRDTs.

Common mistakes

  • Assuming last-write-wins is harmless. It loses data with no error.
  • Expecting CRDTs to enforce rules. They converge, but they cannot keep "never oversell" true. That still needs one owner or consensus.
  • Going multi-region without a policy. Name the rule for each entity, such as last-write-wins per field, a CRDT counter, or one home region.

Key takeaways

  • Conflicts happen whenever more than one replica accepts writes.
  • Last-write-wins always converges, but it drops concurrent writes.
  • Siblings and merges keep every change, at the cost of reader complexity.
  • CRDTs guarantee convergence without coordination, but not a particular answer.
  • Google Docs uses a server, Figma uses per-property rules, and Yjs and Automerge use CRDTs without a server.

Further learning

Kleppmann's "CRDTs: The Hard Parts" covers interleaving anomalies and moving items, which is where real collaborative software gets difficult.

CRDTs: The Hard PartsMartin Kleppmann
Local-first software (Ink & Switch)A new generation of collaborative software that allows users to retain ownership of their data.inkandswitch.com CRDT resources and papers (crdt.tech)Resources and community around CRDT technology — papers, blog posts, code and more.Conflict-free Replicated Data Types