Back to the map

Module 13 · Distributed fundamentals · Lesson 17 of 18

CRDTs

Data types designed so that concurrent updates on different replicas always merge to the same result, with no coordination and no conflicts to resolve. Counters, sets, registers and sequences.

DeepShould-knowSenior 13 minVideoPro Updated Nov 2026

The video walkthrough is part of Pro.

See what Pro includes
Video walkthrough · 2:37 · narrated, with captions

Why it matters

Vector clocks detect concurrent writes and hand the conflict to the application. For many data shapes, that handoff can be eliminated: design the data type so that any two concurrent updates can be merged automatically into the same result everywhere, no matter the order they arrive. That is a CRDT. It is why offline-first apps, collaborative editors, distributed counters and multi-region caches can accept writes anywhere and still converge without a leader, and it is the modern answer to "how do you handle conflicts" in an interview.

The idea

A conflict-free replicated data type is a data structure with a merge function that is commutative, associative and idempotent: merging in any order, any grouping, and any number of times gives the same result. Replicas apply local updates immediately, exchange state or operations whenever they can, and are guaranteed to converge once they have seen the same updates. No locks, no consensus, no manual conflict resolution; the price is that the type's semantics are fixed in advance.

Two flavours

 State-based (CvRDT)Operation-based (CmRDT)
What is shippedThe whole state (or a delta) to be merged with a join functionEach operation, applied at every replica
Network requirementAny; duplicates and reordering are harmless because merge is idempotentReliable, causally ordered delivery (or operations made idempotent and commutative themselves)
CostLarger messages; deltas mitigateSmall messages; needs delivery guarantees
ExamplesG-Counter, OR-Set state, Riak data typesText sequences in Yjs and Automerge (operation logs with causal metadata)

The core types

  1. 1

    G-Counter (grow-only)

    One slot per replica; each replica increments only its own slot; value is the sum; merge is element-wise max. Concurrent increments on two replicas never collide because they live in different slots.
  2. 2

    PN-Counter

    Two G-Counters, one for increments and one for decrements; value is their difference. Likes, inventory estimates, view counts across regions.
  3. 3

    LWW-Register

    A value with a timestamp; merge keeps the higher timestamp. Simple and converges, but it is last-write-wins: concurrent writes lose one, so use it only where that is acceptable or timestamps are hybrid logical clocks.
  4. 4

    OR-Set (observed-remove)

    Each add tags the element with a unique id; remove deletes the tags observed at that replica. A concurrent add and remove of the same element resolves to present (the new tag was not observed by the remover), which matches user intuition. Shopping carts, tag sets, membership lists.
  5. 5

    Sequences (RGA, LSEQ, Yjs's YATA)

    Each character or item gets a unique position identifier that orders it between its neighbours; concurrent inserts at the same spot are ordered deterministically by identifier. This is collaborative text editing without a server deciding.
  6. 6

    Maps and composites

    Maps of CRDTs keyed by field, with per-field merge, build documents: a JSON CRDT (Automerge) composes registers, counters, sets and sequences.
Replica A{milk:t1}Replica B{milk:t1}A: remove milk{} (removed t1)B: add milk{milk:t1, milk:t2}merge{milk:t2}add wins over a concurrent remove: intuitive, deterministic, no coordination
An OR-Set under a concurrent add and remove. The remover deletes only the tags it observed; the concurrent add's new tag survives, so after merge both replicas contain the item.

What CRDTs cannot do

They cannot enforce global invariants that require knowing everyone's state at once: a bank balance that must never go negative, a seat that can be sold once, a unique username. Those need coordination (consensus, a leader or a reservation protocol). CRDTs also carry metadata: tombstones for removed elements, per-replica slots, position identifiers, which grow and must be compacted. And their merge semantics are fixed: an OR-Set says add-wins, and if your product needs remove-wins you need a different type. Choose a CRDT by asking "what should happen under concurrency" and checking the type's answer.

Where they run

Collaborative editors (Figma's multiplayer, Apple Notes, Yjs- and Automerge-based tools), offline-first mobile apps that sync later, Riak's and Redis Enterprise's conflict-free data types for multi-region active-active, distributed counters and presence in chat systems, and SoundCloud's and others' multi-datacenter caches. Operational transformation, next lesson, is the older alternative for text and the one Google Docs still uses.

CRDTs · Backplane