Definition · Concurrent updates, last-writer-wins, and a counter CRDTUpdates are concurrent when no chain of messages orders them — the condition “Vector Clocks and Concurrency” makes decidable. Last-writer-wins resolves them by keeping the state of the replica holding the largest timestamp. A counter CRDT holds one count per replica, merges two states by elementwise maximum and reports the sum.
Both rules produce a single answer from conflicting states, which is what a merge has to do. The difference is what each one is willing to throw away to get there, and that is a number rather than a matter of taste.
four concurrent updates; no replica has seen any other's
replica timestamp delta under LWW CRDT component
A 3 +2 discarded A = 2
B 5 +3 kept B = 3 + 4 = 7
C 4 +1 discarded C = 1
B 9 +4 kept
true total 2 + 3 + 1 + 4 = 10
last-writer-wins B holds the largest timestamp, so B's
register wins = 7
2 updates discarded, worth 3
counter CRDT {A = 2, B = 7, C = 1}, summed = 10
0 updates discarded
Every one of those four updates was acknowledged to a client. Under last-writer-wins two of them stop existing at merge time, with no error raised anywhere, and the value a reader sees afterwards is 7 for a sequence of increments totalling 10. That is not a bug in the implementation; it is what the rule says to do.
The clocks are not the problem
The standard response to this is that the timestamps must be made accurate. Suppose they are exact to the nanosecond. The rule still keeps one replica's register and still discards every update made elsewhere; the only thing that changes is which replica gets to be the winner. What is being lost is not precision in the ordering, it is the fact that there was no ordering to be precise about — the updates were concurrent, and last-writer-wins is a rule for picking one arbitrarily.
The deeper problem is that last-writer-wins treats an increment as a state to be overwritten rather than an operation to be applied. Once +2 has become “A's register reads 2”, there is no way to combine it with “B's register reads 7” except by choosing. The counter avoids the choice by never merging the two into one slot in the first place.
the merge is elementwise maximum on the component vectors
commutative A ∨ B = B ∨ A
associative (A ∨ B) ∨ C = A ∨ (B ∨ C)
idempotent (A ∨ B) ∨ (A ∨ B) = A ∨ B
so every replica converges on the same value regardless of
the order gossip arrives in — commutativity
how the exchanges are grouped — associativity
how often a message is redelivered — idempotence
Example · Why each of the three laws is doing workDrop commutativity and the value depends on which replica gossiped first, so two replicas that exchanged the same information in opposite orders disagree for ever. Drop associativity and it depends on how the exchanges were grouped, which is a topology detail nobody controls. Drop idempotence and a redelivered message — the thing every network does under retry — double counts. Elementwise maximum has all three, which is why the convergence needs no coordination at all: no ordering, no exactly-once delivery, no leader.
A grow-only counter is the easy case and it should be read as an existence proof rather than a general solution. Sets with removals, registers holding documents, and ordered sequences all need more machinery, and some conflicts are genuinely business decisions that no merge rule should be making. What transfers is the question: for this data type, what does my merge rule discard, and can I count it?