Two people edit the same offline document and later sync — normally you get a merge conflict. A Conflict-free Replicated Data Type (CRDT) is designed so that never happens: replicas can be updated independently, concurrently, without any coordination, and when they eventually exchange state they always converge to the same value — no conflicts, no consensus, no central authority. The trick is choosing a merge function that is commutative (order doesn’t matter), associative (grouping doesn’t matter), and idempotent (merging twice is harmless). The classic example, a grow-only counter, stores a per-replica count and merges by taking the element-wise max. Increment the replicas, merge them in any order you like, and watch them all land on the same number.
A data type whose replicas can be updated independently and always merge without conflict.
G-Counter
A grow-only counter: each replica keeps its own count; the value is their sum.
merge
Combine two replica states — here, take the element-wise max of the per-replica counts.
convergence
After enough merges, every replica holds the identical state (strong eventual consistency).
crdt.js — max merge, always converges
Ready
Three replicas of a grow-only counter. Each holds a per-replica count vector; the counter’s value is the sum. Increment replicas independently, then merge (element-wise max) — in any order — and watch them converge. A++/B++/C++ then merge.
0
A value
0
B value
0
C value
How it works
A grow-only counter (G-Counter) makes the CRDT magic concrete. Instead of one shared number (which two replicas would clobber), each replica keeps a small vector: entry i is “how many increments replica i has done, as far as I know.” A replica only ever increments its own entry, so no two replicas can conflict on the same slot. The counter’s value is just the sum of the vector. Merging two replicas takes the element-wise max — and max is commutative, associative, and idempotent, which is exactly the mathematical structure (a join-semilattice) that guarantees convergence no matter what order, or how many times, replicas sync. So you can partition the network, let replicas drift apart, and reconnect them in any pattern: once every increment has propagated, all replicas compute the identical sum. This is strong eventual consistency — available and partition-tolerant, with automatic conflict-free convergence.
1
Each replica owns one slot
A G-Counter stores a per-replica count vector. A replica only ever increments its own slot, so concurrent increments on different replicas never touch the same entry — no conflict is possible.
2
Value is the sum
To read the counter, sum all the per-replica counts. Each replica may have a different view until it has merged in the others’ updates.
3
Merge by element-wise max
When two replicas sync, each entry becomes the max of the two values — adopting the higher (more up-to-date) count for every replica. Max is commutative, associative, and idempotent.
✓
Converge no matter the order
Because the merge has that algebraic structure, replicas converge to the identical state regardless of the order or number of merges — strong eventual consistency, with no coordination.
Coordination
none needed
Merge
commutative/assoc/idempotent
Guarantees
convergence
Used in
Redis, Riak, collab apps
The code
# grow-only counter (G-Counter) CRDT for replica r of n
counts = [0] * n
def increment():
counts[r] += 1 # only ever your own slotdef value():
return sum(counts) # the counter's valuedef merge(other):
for i in range(n):
counts[i] = max(counts[i], other.counts[i]) # join by max# max is commutative + associative + idempotent => replicas# converge to the same value no matter the merge order.
Quick check
1. What property must a CRDT’s merge function have?
Those three properties (a join-semilattice) guarantee that merging replicas in any order, any number of times, always reaches the same state. That is what lets replicas sync without coordination or conflicts.
2. In a G-Counter, why can concurrent increments never conflict?
A replica only ever touches its own entry in the vector. Two replicas incrementing at the same time modify different slots, so there is nothing to conflict over — merging by max just adopts both.
3. What does "strong eventual consistency" mean for CRDTs?
Replicas may differ temporarily, but once every update has propagated, the CRDT’s conflict-free merge guarantees they all reach the exact same state — achieved without any coordination or consensus.
FAQ
What is a CRDT?
A Conflict-free Replicated Data Type: a structure replicated across nodes, updated independently and concurrently without coordination, and merged so all replicas converge with no conflicts. Two flavors — state-based (merge whole state via a commutative/associative/idempotent merge) and operation-based (broadcast commutative ops) — giving strong eventual consistency.
What are common CRDT types?
Grow-only and PN counters; grow-only, two-phase, and observed-remove sets (OR-Set) supporting add/remove; last-writer-wins and multi-value registers; and sequence CRDTs (RGA, LSEQ) for collaborative text. Each defines updates plus a merge satisfying the convergence properties.
Where are CRDTs used?
Collaborative editors and note apps (real-time, offline-friendly collaboration), distributed databases (Redis Active-Active, Riak, Cosmos DB), carts and counters in eventually-consistent stores, and local-first software where devices edit offline and sync later — anywhere you need automatic, multi-writer, offline-capable merges.
Consensus (Raft, Paxos) forces agreement on one total order — strong consistency, but needs coordination and a majority, sacrificing availability under partitions. CRDTs never coordinate, stay available under partitions, accept temporary divergence, and rely on their merge to converge. Consensus for "one answer now"; CRDTs for "everyone edits, reconcile automatically."