The full picture
| Model | Promise | Cost | Where you meet it |
|---|---|---|---|
| Linearizable | single-copy illusion, real-time ordered | quorum/leader round-trip per op | etcd reads (default), ZooKeeper writes, DynamoDB consistent reads, compare-and-swap |
| Sequential | same total order everywhere, not real-time | consensus for writes, no read coordination | ZooKeeper reads (stale until you call sync), classic replicated state machines |
| Causal | happens-before respected; concurrent = unordered | metadata (vector clocks), no coordination | COPS, MongoDB causal sessions, most chat apps |
| Eventual | convergence if writes stop | none — async replication | DNS, S3 (historically), Cassandra ONE, CDNs |
- The real-time clause is what makes linearizability expensive: if a write completes and then my read starts, I must see it — even from a different client on a different node. That forbids serving reads from a lagging follower without checking, which is why 'read from replicas' is a correctness change, not a performance tweak.
- Causal consistency is the sweet spot most people want: it kills the anomalies users actually notice — a reply appearing before the message it answers, a delete appearing to un-delete. And crucially it is achievable while remaining available under partition, which linearizability provably is not.
- Eventual is a floor, not a design: 'eventually consistent' with no bound is untestable. What makes it usable in production is a stated convergence window (replica lag p99 < 200ms), monitoring on it, and a conflict-resolution rule you chose deliberately.
- Watch the trap of 'strong consistency' — a marketing word, not a model. Ask which one is meant: DynamoDB's 'strongly consistent read' is linearizable per key, not across keys; Cassandra's QUORUM read+write gives you quorum overlap, not linearizability (a partially applied write can be seen by one read and not the next — only LWT/Paxos is linearizable there).
- Even the coordination services differ, and it's a favourite probe: etcd serves linearizable reads by default (it pays a ReadIndex round-trip;
WithSerializableopts out). ZooKeeper does not — its writes are linearizable but reads are served locally by any server and may be stale, so ZooKeeper is sequentially consistent unless you issuesyncbefore the read. 'Which of your reads are linearizable?' is a sharper question than 'is this database strongly consistent?'.