What three algebraic properties must a CRDT's merge function satisfy to guarantee replicas converge, and how does an LWW-Register (last-write-wins register) satisfy them while still having a well-known failure mode?
answer
- commutative: order doesn't matter
- associative: grouping doesn't matter
- idempotent: re-merge is a no-op
- join-semilattice = convergence guarantee
- LWW arbitrates, doesn't merge concurrent writes
basics
~20 sA CRDT's merge rule has to give the same answer no matter which order you combine copies in (commutative), no matter how you group multiple merges together (associative), and merging something with itself again changes nothing (idempotent). An LWW-Register just keeps whichever write has the latest timestamp - that math works, but it means one of two concurrent writes is always thrown away, which can silently lose data.
solid answer
~50 sThe three required properties are commutativity (merge(a,b) = merge(b,a) - arrival order doesn't matter), associativity (merge(merge(a,b),c) = merge(a,merge(b,c)) - grouping/batching doesn't matter), and idempotency (merge(a,a) = a - duplicate delivery is harmless). Together these mean replicas form a join-semilattice under merge, so applying merges in any order, any number of times, over any subset that eventually includes everything, converges to the same state - the formal basis of strong eventual consistency. LWW-Register stores (value, timestamp); merge keeps whichever pair has the higher timestamp (with a deterministic tie-break, e.g. replica ID). Max-by-timestamp is commutative, associative, and idempotent, so it's a valid CRDT - but its failure mode is that concurrent writes aren't merged, they're arbitrated: one write is kept, the other discarded entirely, fine for 'cursor position' but silently loses data for something like 'the set of tags a user is editing.'
go deeper
Should be able to restate the three properties in plain language (order doesn't matter, grouping doesn't matter, repeats don't matter) and know that LWW keeps the newer write and drops the older one.
Should connect the three properties to why they're needed given unreliable, unordered, duplicating networks, and describe LWW-Register's (value, timestamp) representation.
Should articulate the join-semilattice framing and explain LWW-Register's 'arbitrates, doesn't merge' limitation precisely, including clock-skew and tie-break subtleties.
Should know the Multi-Value Register alternative and reason about when arbitration (LWW) versus preservation (MV-Register, OR-Set-style) is the right choice for a given field, including how compound CRDT structures get built from these primitives.
## The three algebraic properties A merge function used by any CRDT must satisfy three algebraic properties for replicas to be guaranteed to converge to the same state regardless of communication patterns. 1. **Commutativity** means `merge(a, b) = merge(b, a)`: the order in which two states or updates are combined doesn't change the result, which matters because in an asynchronous network there is no guarantee two replicas receive gossip from each other in the same relative order. 2. **Associativity** means `merge(merge(a, b), c) = merge(a, merge(b, c))`: however the merges are grouped or batched — two at a time in any grouping, or all at once — the result is identical, which matters because real systems batch, retry, and reorder merge operations for efficiency and fault tolerance, and the result must not depend on those implementation choices. 3. **Idempotency** means `merge(a, a) = a`: merging a state with itself, or re-merging a state already incorporated, changes nothing, which matters because networks routinely duplicate messages (retries, at-least-once delivery, gossip re-broadcast) and a CRDT must be immune to seeing the same update more than once. ## Why the three add up to convergence Together, these three properties mean the set of possible replica states, ordered by "has observed at least as much as," forms a **join-semilattice**, and merge computes the least upper bound (join) of two states in that lattice. This is the mathematical backbone of **strong eventual consistency**: once two replicas have (directly or transitively, through any path of merges) incorporated the same set of underlying updates, they are in exactly the same state — with no possibility of divergence based on the order, batching, or duplication of how those updates were exchanged. This is what removes the need for consensus or locking: instead of agreeing in real time on a global order of operations, replicas only need the guarantee that whatever order they observe things in, they land in the same place eventually. ## How LWW-Register satisfies them **LWW-Register** (last-write-wins register) is the CRDT for representing a single, arbitrarily-typed value — like "the current display name" or "the current cursor position" — where each write is stamped with a timestamp (a physical clock reading, or more robustly a logical/hybrid clock plus a tie-breaking replica ID to guarantee two writes are never exactly equal). `merge(a, b)` simply returns whichever of the two `(value, timestamp)` pairs has the higher timestamp, with the tie-break applied on exact ties. This satisfies all three properties: - it's **commutative and associative** because "keep the max by timestamp" doesn't depend on evaluation order; - it's **idempotent** because merging a value with an identical copy of itself returns that same value. Reads simply return the current pair's value. ## The well-known failure mode The well-known failure mode is that LWW-Register doesn't actually merge concurrent writes — it **arbitrates** between them, keeping exactly one and permanently discarding the other, the same way a plain last-writer-wins resolution strategy would. If two users concurrently edit a shared "status message" field, only one edit survives; the other is silently gone, with no record a conflict even occurred. This is a legitimate and useful CRDT (it satisfies the three properties and converges deterministically), but "converges deterministically" is a weaker guarantee than "preserves all updates" — engineers sometimes conflate the two and are surprised when LWW-Register "loses" data during genuinely concurrent writes. It's also sensitive to **clock skew**: if replicas' physical clocks aren't reasonably synchronized, an update a human would consider "later" can lose to an update from a replica whose clock is fast, producing outcomes that look wrong even though they're a technically correct, deterministic LWW resolution. ## Where it ships - LWW-Register is the standard building block for individual fields of compound CRDT structures — e.g. a CRDT map is often built as a set of `(key, LWW-Register)` pairs, where each field independently resolves conflicts by timestamp while key membership is handled by a separate structure like an **OR-Set**. - **Riak KV** and **Redis CRDB** both expose an LWW-style register type as one of their native CRDT primitives for exactly this "single scalar field, occasional concurrent writes acceptable to arbitrate" use case. - **Cassandra's** own last-write-wins conflict resolution for cell values follows the identical algebraic pattern, even though Cassandra doesn't market itself as CRDT-based.
- Why is a tie-break by replica ID needed on top of the timestamp in LWW-Register?Physical or even logical clocks can produce identical timestamps for two genuinely concurrent writes from different replicas, and if merge can't determine a strict winner, different replicas could each keep their own local write as 'the max,' breaking determinism; adding a secondary, globally comparable tie-breaker (like replica ID) guarantees every replica computes the identical winner even on an exact timestamp tie.
- Is 'first-write-wins' (keep the lower timestamp) also a valid CRDT merge rule?Yes - 'min by timestamp' is exactly as commutative, associative, and idempotent as 'max by timestamp,' so an FWW-Register is an equally valid CRDT; it's just a different, less commonly useful arbitration policy, e.g. useful for 'the first person to claim this slot wins' semantics.
- Can you build a register that preserves both concurrent writes instead of picking one?Yes - a Multi-Value Register (MV-Register) keeps the set of all causally-concurrent values (detected via vector clocks) rather than arbitrating a single winner, surfacing all of them to the application or user to resolve manually; this trades LWW's automatic-but-lossy resolution for a design that never silently drops data but pushes reconciliation up a layer.
Commutative/associative/idempotent merge is like tracking a highest-ever temperature reading by always keeping the max seen so far, no matter which order the readings come in, how you group the comparisons, or whether the same reading gets reported twice - you always land on the true maximum. LWW-Register is like a whiteboard where whoever wrote most recently (by a timestamp in the corner) is the version that stays visible - useful, but the earlier writer's note is erased, not saved anywhere.
saying these in an interview costs you the question
- Can't state what commutative/associative/idempotent mean concretely
- Thinks LWW-Register preserves both concurrent writes
- Doesn't know clock skew affects LWW outcomes
- Believes any merge function that 'looks reasonable' is automatically a valid CRDT merge without checking the three properties