How it works
Start with the conflict semantics, not the replication protocol. If two disconnected devices change the same data, decide what should survive: both increments, both text insertions, or one chosen value. A CRDT encodes those decisions into its data model and operations.
A state-based CRDT sends its state, or suitable deltas, to other replicas. Its merge is associative, commutative, and idempotent, and updates advance state within a defined partial order. Those properties let replicas merge repeated and reordered state exchanges safely; convergence still requires eventual propagation of updates.
A grow-only counter illustrates this model. Each replica owns one component: replica A might hold [3, 0] and replica B [0, 2]. Merge takes the maximum of each component, producing [3, 2], and the visible count is their sum, 5. Taking the maximum of the two visible totals would lose increments; adding the totals repeatedly would double-count them.
Operation-based CRDTs exchange operations instead of full states. Concurrent operations commute under the type's delivery assumptions. Many designs require causal delivery and duplicate suppression, so do not assume arbitrary at-least-once messaging is sufficient without additional protocol support.
Different types handle different conflicts. A positive-negative counter uses two grow-only counters to support increments and decrements. An observed-remove set tracks uniquely tagged additions: a removal deletes additions it has observed, while a concurrent unseen addition survives. This is an explicit add-wins policy, not a universal definition of deletion.
Text CRDTs give inserted elements stable identities and deterministically order concurrent insertions. Deletes reference identities rather than unstable character offsets, and cursors can anchor to those identities. The service still needs durable storage, reconnect synchronization, authorization, and a safe strategy for removing obsolete metadata.
A worked example
Merging a counter after a regional partition
Suppose three regions maintain a grow-only counter with components [A, B, C]. All begin at [100, 80, 20], so the displayed total is 200. During a partition, A accepts 7 increments and stores [107, 80, 20]; B accepts 4 and stores [100, 84, 20]. When connectivity returns, component-wise maximum produces [107, 84, 20], totaling 211. Replaying either state changes nothing, so repeated synchronization cannot double-count these updates. Each region must durably maintain its own component and recover it safely after a crash. This handles replication duplicates, not duplicate business requests: if one client action is submitted twice and incremented twice, the application still needs request deduplication.
Trade-offs to say out loud
- Available writes versus immediate agreement
- Replicas can accept supported local updates during a partition, but readers may see different values until updates propagate.
- Deterministic results versus application intent
- An add-wins set or text sequence can converge perfectly while producing a result users did not expect.
- Metadata and bandwidth
- Replica components, element identifiers, causal history, and tombstones can consume substantial space and synchronization bandwidth.
- Safe metadata cleanup
- Compaction must account for delayed operations and offline replicas, often requiring a causal-stability rule or a forced snapshot resynchronization.
- Limited invariant enforcement
- Ordinary counters and sets do not enforce hard inventory limits, unique ownership, or cross-object constraints without coordination or a specialized rights-allocation design.
- Protocol and operational complexity
- Replica identity, duplicate handling, crash recovery, schema changes, and convergence testing remain engineering responsibilities.
When to reach for it
- Users must edit shared data while offline and merge their work after reconnecting.
- Multiple regions must accept writes during network partitions, and temporary disagreement is acceptable.
- The data has clear merge semantics, such as accumulating increments or retaining concurrent insertions.
- The interview requires an explicit answer for concurrent writes rather than simply saying that replicas eventually synchronize.
How to bring it up in the interview
- State the requirement first: 'We need offline edits without rejecting concurrent changes.' Then name the specific CRDT and explain its conflict policy.
- Walk through two replicas making concurrent updates and merging in opposite orders; show why both reach the same result.
- Separate state-based merge guarantees from operation-delivery requirements, and expect questions about retries, missing updates, and causal dependencies.
- Draw the persistence and reconnect path: what an acknowledgment guarantees, how updates are replayed, and when a client must download a snapshot.
- Defend the boundary: use CRDTs for mergeable state, not as a blanket replacement for transactions; expect probes about tombstone cleanup, replica retirement, and business invariants.
Common mistakes
- Calling any last-write-wins database a solution to concurrent editing without explaining which updates it discards.
- Assuming every CRDT tolerates duplicated or arbitrarily reordered operations without protocol support.
- Confusing convergence with linearizability, durability, or preservation of user intent.
- Using an increment/decrement counter for likes without maintaining each user's like state, allowing retries or concurrent actions to corrupt the total.
- Deleting tombstones or reusing replica identities without considering old operations that may arrive later.
Where it comes up
Interview questions where crdts is part of a strong answer, and why.
- Design Google DocsText CRDTs directly address concurrent edits, stable cursor anchors, and synchronization after disconnected editing.
- Design a distributed key-value storeCRDT-backed values provide explicit merge semantics for writes accepted by different replicas during a partition.
- Design Facebook likes at scaleA multi-writer design must define convergent per-user like/unlike semantics before deriving replay-safe aggregate counts.
Questions people ask
What does CRDT stand for?
CRDT stands for conflict-free replicated data type. It defines data and update rules that let replicas converge despite concurrent changes, provided the implementation satisfies the type's synchronization and delivery requirements.
What is the difference between CRDTs and operational transformation?
Operational transformation adjusts operations against concurrent operations so they can be applied consistently; many collaborative editors use it with a server-assigned order. Text CRDTs instead use stable identities and deterministic integration rules. Both require careful synchronization and persistence, and neither automatically guarantees that merged edits match human intent.
Do CRDTs provide strong consistency?
CRDTs are commonly used for strong eventual consistency: replicas that incorporate the same updates reach equivalent states, and updates eventually propagate under the system's assumptions. This is not linearizability, and it does not mean every read sees the latest write. Extra coordination may still be necessary for constraints such as never overselling inventory.