skip to content

What is the structural difference between a state-based CRDT (CvRDT) and an operation-based CRDT (CmRDT), and what does each approach require from the network layer to guarantee convergence?

level: middleimportance: must knowfreq 60%

answer

  1. state-based = ship whole state, merge = join
  2. op-based = ship delta, needs causal reliable delivery
  3. CvRDT tolerant of dropped/duplicate messages
  4. CmRDT bandwidth-efficient but delivery-sensitive
  5. Shapiro et al. proved equivalence

basics

~20 s

One kind of CRDT sends its whole current value to other computers, and they combine values together (state-based). The other kind sends just 'what changed' as a small message, applied in a way that works regardless of order (operation-based). The first tolerates lost or duplicate messages better; the second sends less data but needs more careful delivery.

solid answer

~40 s

A CvRDT (convergent/state-based) replica ships its entire local state to peers, or gossips it periodically; a peer merges an incoming state into its own via a function that must be commutative, associative, and idempotent over a join-semilattice - this makes CvRDTs naturally tolerant of duplicate delivery, reordering, and even missed messages, since the next full-state message re-establishes convergence. A CmRDT (commutative/operation-based) instead ships small operations (e.g. 'increment', 'add element X'); operations must commute with each other, and delivery must be reliable and causally ordered, because there's no full state to fall back on - a dropped operation is permanently lost. CmRDTs trade a stronger delivery requirement for far less bandwidth per update, especially valuable for large states like text documents.

go deeper

for a junior

Should be able to say, roughly, that one kind sends the whole value and the other sends just the change, and that sending just the change is more fragile if a message gets lost.

for a middle

Should name the specific requirement each imposes on the network (state-based tolerates loss/duplication/reordering; op-based needs causal, exactly-once delivery) and give one reason to prefer each.

for a senior

Should explain the semilattice/join formalism behind CvRDT convergence and the prepare/effect split in CmRDT design, and reason about which to pick given a system's transport reliability and state size.

for a principal

Should know delta-state CRDTs as the practical middle ground used in real systems, and be able to reason about the operational cost (causal-broadcast infrastructure vs. bandwidth) of each choice at scale.

## State-based: the CvRDT **State-based CRDTs**, formally called **CvRDTs** (convergent replicated data types), represent a replica's data as a single value drawn from a mathematical structure called a **join-semilattice** — a set with a partial order and a "least upper bound" (join) operation for any two elements. 1. A write mutates the local state **monotonically** (moves it "up" the lattice, e.g. a G-Counter's slot only increases). 2. To synchronize, a replica periodically ships its **entire current state** to peers (directly, or via gossip/anti-entropy). 3. The receiving replica calls `merge(local, incoming)`, which computes the **join** of the two states. Because join in a semilattice is commutative, associative, and idempotent by definition, CvRDT convergence is automatic: any two replicas that have (directly or transitively) observed the same set of updates end up in the same state, regardless of the number of times, order, or duplication of the merge messages. ## Operation-based: the CmRDT **Operation-based CRDTs**, **CmRDTs** (commutative replicated data types), instead ship the delta — the operation itself — rather than the resulting state. Because there is no full-state reconciliation step to fall back on, the correctness burden moves from the merge function to the **delivery channel**: - Operations that don't commute unconditionally (e.g. an add and a remove of the same set element) must be delivered in **causal order** (applied only after everything they causally depend on has already been applied). - Every operation must be delivered **exactly once** — a dropped message means a permanently missing update, and a duplicated message means a corrupted counter. CmRDT designs typically split each operation into a **prepare** phase (executed once, at the origin) and an **effect** phase (executed at every replica when the operation is delivered), with effects specifically designed to commute pairwise; Shapiro et al.'s 2011 formalization of both CvRDT and CmRDT proved their equivalence in expressive power. ## The trade, in opposite directions The two designs trade bandwidth against delivery-reliability requirements in opposite directions — CvRDT's *ship the whole state* approach against CmRDT's *ship the delta* approach: | CvRDT | CmRDT | |---|---| | Any missed, reordered, or duplicated gossip message is **self-healing** — the next full-state exchange re-merges everything and nothing is permanently lost — a natural fit for unreliable, best-effort transports like gossip over UDP. | **Bandwidth-efficient**: only what actually changed is sent, which matters enormously for large, frequently-mutated structures like collaborative text. | | The cost is bandwidth and CPU: shipping the entire state every sync round is wasteful once the state is large, and the merge itself can be expensive. | But it demands a reliable **causal-broadcast layer** (a message queue with per-sender sequence numbers and causal buffering), which is real infrastructure to build and operate correctly. | ## How each one fails in production - **A common production failure with CmRDTs** is underestimating the delivery guarantee: teams wire operations through an ordinary at-least-once queue without deduplication or causal buffering, and either lose operations during a broker failover (permanent data loss, no full-state fallback) or double-apply retried operations. - **A common CvRDT failure** is treating periodic full-state gossip as cheap indefinitely — as the state grows (e.g. an OR-Set that has accumulated years of tombstones), each sync round's bandwidth and merge CPU grows with it, silently degrading until sync rounds fall behind real-time write rates, widening convergence lag. ## Where each one ships - **Riak's** built-in CRDT types are state-based (CvRDTs), gossiped between nodes with causal-context metadata attached, chosen because Riak's underlying transport (Dynamo-style read-repair and anti-entropy) already exchanges full replica states rather than a reliable operation log. - Collaborative editors built with **Yjs** use an operation-based-flavored design over a reliable WebSocket/relay connection specifically because shipping the entire document state on every keystroke would be far too expensive — each keystroke is instead a small, causally-tagged operation.

  • Could you build a hybrid that sends deltas most of the time but falls back to full state?
    Yes - this is called a delta-state CRDT (δ-CRDT): it ships small delta-states (a fragment of the lattice representing recent local changes) most of the time for bandwidth efficiency, but because deltas are still states, they can be merged with the normal join operation and safely re-sent or batched, recovering CvRDT's tolerance for loss/duplication without paying full-state cost every round.
  • Why does a CmRDT need causal delivery specifically, not just in-order delivery from a single sender?
    Because operations from different replicas can be causally dependent through indirect paths - e.g. replica B's remove was issued after B observed replica A's add - so a receiver must apply A's add before B's remove even though they arrive from different senders; per-sender FIFO ordering alone doesn't capture cross-replica causal dependencies.
  • If bandwidth isn't a concern, is there any reason to still prefer CmRDT over CvRDT?
    Rarely - if bandwidth is genuinely free, CvRDT's simpler failure model (self-healing under message loss/duplication/reordering) is usually preferable; CmRDT is chosen specifically to save bandwidth/CPU on large states, so absent that pressure it mostly just adds delivery-infrastructure complexity for no benefit.

CvRDT is like mailing someone your entire updated address book every week - wasteful, but if a letter gets lost or arrives twice it doesn't matter, next week's full copy fixes everything. CmRDT is like mailing individual index cards for each change ('added: Jane's number') - cheap per card, but if one card is lost in the mail, that change is gone forever unless you track exactly which cards arrived.

saying these in an interview costs you the question

  • Says CmRDT and CvRDT differ only in syntax, not delivery requirements
  • Thinks CvRDT requires reliable ordered delivery
  • Can't explain why a dropped operation is catastrophic for CmRDT but not CvRDT
  • Confuses 'operation-based' with just 'sending a diff of the state'
  • Unaware that op-based CRDTs need causal, not just FIFO, delivery

context