Two people edit the same document at the same time from two devices, offline, and when they finally reconnect the result is not a tangle of broken cells or a blunt “last writer wins”: both edits survive. How is that possible without a server arbitrating? The answer lives in a family of data structures called CRDTs (Conflict-free Replicated Data Types), the mathematical backbone of tools like Figma, Notion or Google Docs.
A CRDT is a data structure that can be replicated across many nodes, modified in parallel and later merged without losing any update and without central coordination. The key is designing the merge operation to be commutative, associative and idempotent: no matter the order in which each replica arrives, or whether a message arrives twice, the result is always the same. That makes systems with no ordering guarantees — networks with outages, offline phones, cloud replicas — converge on their own.
The property that makes it work
Mathematically, a CRDT guarantees a property called strong eventual consistency: any pair of replicas that have seen the same set of updates, even in a different order, end up in exactly the same state. To achieve that, all CRDTs split the work between two ideas: either every node accumulates state that is fused with that of the others (state-based), or every node re-broadcasts operations (called updates) that the rest apply (operation-based).
The simplest case is the G-Counter, an increment-only counter. A normal shared counter does not work: if two nodes increment at once, who adds what? The G-Counter solves it by splitting the counter into one cell per node. Each replica only touches its own cell, and the merge operation adds up the cells of all nodes. Because addition is associative and commutative, everyone converges on the same total. If you also need to subtract, the PN-Counter appears, keeping two G-Counters: one for increments and one for decrements.
Registers and sets
The LWW-Register (last-writer-wins register) is the CRDT behind a settings field in a notes app: every update carries a logical timestamp (a logical clock, not the wall clock, which lies under replication), and on merge the version with the highest timestamp wins. It is simple and practical, though it loses information if two different edits come from the same node.
Replicated sets are more interesting. The OR-Set (observed-remove set) lets you add and remove elements without deleted ones resurrecting by mistake: when an element is added it gets a unique identifier (a UUID), and a removal only deletes the exact marked version, not “everything with that name”. Thanks to that identity-by-observation, the classic bug of a deleted element reappearing after a merge is avoided.
The real challenge: lists and text
All of the above solves numbers and sets. The hard problem is sequences: a list where you insert and delete at specific positions. Here the state is the order of elements, and two insertions at the same position must both remain. Modern solutions — the YATA algorithm from the Yjs library and the RGA (Replicated Growable Array) from Automerge — give every operation a unique identifier and define rules of ordering between the two documents based on which operation “saw” which first (a causality relation expressed through vector clocks). This is what lets two people type in the same sentence in Google Docs and have both texts survive.
The cost of that convergence is memory and history: you must keep metadata (identifiers, clocks) to be able to merge. That is why these systems usually store the history for a while and “prune” it once they are sure no more out-of-order information can arrive.
CRDTs are not just for text editors
The same machinery powers distributed and edge databases, caches on devices that flip between online and offline, collaborative design tools, and contact or task-list sync systems. Understanding a CRDT is understanding that replication does not have to be guaranteed chaos: you only need to choose well what gets replicated and how it merges.





