advanced25 min studyLesson 255 in Engineering

Operation-based CRDTs: commutativity needs a delivery contract

Separate preparing an update, delivering its effect, deduplicating retries, and respecting causal dependencies.

On this page

What you’ll understand

  • Explain why repeated non-idempotent operations need duplicate suppression.
  • Distinguish concurrent-operation commutativity from causal delivery.
  • Trace unique operation identities through reordering and retries.

Instead of shipping a whole accumulated state, an operation-based replicated type propagates prepared effects. This can be compact, but the network contract becomes central. Concurrent operations must commute under the design’s conditions, while causally related operations may require ordered delivery. A retry is not automatically a new user action. Correctness depends on identifying the operation and applying its effect according to the protocol, including after a process restart.

Prepare the effect using the origin context

A source can inspect its current state while preparing an update, then produce an effect containing enough information for downstream replicas. For an observed-remove set, for example, a remove must identify the add tags it actually observed, rather than telling every receiver to delete whichever additions happen to exist on arrival. Preparation and effect application are separate conceptual phases, even if an implementation combines them in one API. A downstream replica should not independently reinterpret the original user command against unrelated local context.

In the standard causal operation-based model, reliable delivery eventually makes each effect available at correct replicas, causal order preserves prerequisite effects, and concurrent effects commute. Some particular types need weaker ordering; other designs incorporate additional metadata to tolerate stronger reordering. State the actual contract rather than claiming all operation-based CRDTs work over arbitrary lossy, duplicated messages. A convergence proof that assumes once-only effect delivery does not survive blindly replaying a non-idempotent increment every time a network retry arrives.

effect⁡a(effect⁡b(s))=effect⁡b(effect⁡a(s))(a∥b)\operatorname{effect}_a(\operatorname{effect}_b(s))=\operatorname{effect}_b(\operatorname{effect}_a(s))\quad(a\parallel b)
The equality is the required commutativity of concurrent effects on applicable states in this model. It does not assert that causally dependent operations may always be reversed, or that duplicate applications are harmless.↔ Scroll wide equations horizontally.

Count user operations, not packet deliveries

A signed counter whose operations add fixed deltas has commuting effects, but adding the same delta twice still counts it twice. Give each logical operation a unique identity and ensure the dissemination layer applies its effect once, or design an idempotent representation that absorbs repeats. Durable deduplication state, actor epochs, and replay boundaries matter across crashes. A locally generated operation that was already applied must not be applied again merely because the source receives its own replicated message.

The phrase exactly once needs a boundary. A transport may redeliver, while a consumer transaction records an operation identity together with its state change. An external email or payment is another side effect that is not automatically protected by an in-memory CRDT’s delivery logic. Likewise, forgetting deduplication records requires evidence that old messages cannot return or that an epoch rejects them. Convergence of the in-memory type does not provide unlimited replay protection outside its documented retained history.

Q=Q0+∑o∈OuniqueΔoQ=Q_0+\sum_{o\in O_{\rm unique}}\Delta_o
O_unique contains each accepted logical operation identity once, Δ_o is its signed integer effect, and Q is a dimensionless count. Summing packet deliveries instead is wrong when packets repeat a logical operation.↔ Scroll wide equations horizontally.

Delivery liveness has a capacity cost

If accepted operations accumulate faster than the replication channel can deliver them, the backlog grows even when every algebraic condition is correct. Measure pending effects, oldest-undelivered age, retry traffic, and the size of deduplication metadata. Durable logs and anti-entropy can repair gaps, but their retention and recovery rules must align. A permanently lost accepted operation contradicts eventual delivery; good local latency alone cannot establish eventual convergence. Overload policies should be explicit about whether an operation was actually accepted.

The queue lab gives a limited view of this delivery-capacity pressure. Reset, set arrival rate λ=4 and service rate μ=3, predict backlog 4+t, then Step or Play. Reset again and set λ=2, μ=3 to predict drainage to zero at t=4. Editing controls alone preserves elapsed time, so Reset is needed for this fresh comparison. The fluid queue contains no operation identities, causality, retries, or deduplication; its separately labeled M/M/1 estimate has additional stochastic assumptions.

Three operations, four delivered packets

Starting from zero, unique effects are A1:+3, A2:−1, and B1:+2. A2 causally follows A1. A receiver sees packets A1, B1, A1 again, A2.

  1. Track identities as well as deltas. The first A1 contributes three and B1 contributes two, giving five. Their order can be exchanged for this additive counter without changing the result.

  2. The repeated A1 packet has an identity already applied, so a correct once-only effect layer suppresses it. The state remains five rather than incorrectly becoming eight.

  3. Applying A2 contributes minus one, yielding four. Naively adding every packet would instead produce seven. This arithmetic type happens to commute even for A1 and A2, but the general causal delivery requirement is not removed for other data types.

The result

The correct total is four from three unique operations. Packet count and logical update count differ, and causal ordering remains a type-specific obligation.

Explore the model

Interactive lab

Interactive lab · queue

Accepted effects need delivery capacity

Reset, set λ=4 and μ=3, predict backlog 4+t, then Play or Step. For a fresh draining comparison Reset and set both λ=2 and μ=3. This fluid queue does not model CRDT delivery, duplicates, or causality.

Accepted effects need delivery capacityFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forA delivery backlog can grow despite correct merge algebra; capacity and replay correctness are different requirements.

Check your understanding

A counter’s increment effects commute. Is applying a retried +1 operation twice necessarily safe?

Try it yourself

A receiver starts at ten and accepts unique deltas X:+2, Y:−3, Z:+4. Packets arrive X,Y,Y,Z. Compute correct and naive totals, and identify what a crash must preserve.

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Sum unique operation identities for the correct total, and include the repeated Y only in the naive total.

Compare with the solution

The correct result is 10+2−3+4=13. Blind replay produces 10+2−3−3+4=10. Recovery must preserve the state-change/deduplication relationship or use an equivalent replay-safe representation; keeping only an in-memory seen set is insufficient if old packets may return after restart.

Take it with you

  • Prepare effects with the origin’s intended causal context.
  • Commutativity, idempotence, causal order, and eventual delivery are different conditions.
  • Retries and recovery require a defined durable operation-identity boundary.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.