Consistency models
What a reader is promised about writes they did not see happen.
01The intuition
The problem it solves
You post a comment on a friend's photo, refresh the page, and the comment is gone. Ten seconds later it is back. Nothing was lost; your refresh was answered by a server that had not yet heard about the comment. Now imagine that happening to a bank balance: you deposit money, check the balance, and see the old number. Same mechanism, very different feelings.
Once data lives on more than one machine, a reader can be served by a copy that is behind. A consistency model is the written promise about what a reader may see. Without naming the promise, two engineers will build two different systems from the same diagram and argue about which one is broken.
Build it one piece at a time
Step 1: one copy. With a single database there is one story: every read sees every earlier write. Call this the strong case. It is what people assume by default.
Step 2: add a replica, and lag. Writes go to the leader, reads go to a follower 50 ms behind. A reader may now see data up to 50 ms old. This is eventual consistency: if writes stop, all copies become identical eventually, but during the lag different readers see different histories.
| Promise | What a reader is told | Cost |
|---|---|---|
| Eventual | you will see every write at some point, in some order | cheapest; any replica can answer |
| Read-your-writes | you always see your own writes | route a user's reads to the leader briefly, or wait for the replica to reach the user's write version |
| Monotonic reads | you never see time go backwards | pin a user to one replica |
| Causal | if B was written after seeing A, nobody sees B without A | track dependencies between writes |
| Linearizable (strong) | every read sees the latest completed write, as if there were one copy | reads go through the leader or a quorum; a cross-region round trip per operation |
Step 3: pick a promise per operation, not per system. The comment can be eventual. The balance read before a withdrawal must be linearizable. A feed can be causal (a reply must never appear before the post it answers). Most real systems mix all three, and the design says which call gets which.
Step 4: pay for the strong ones. A linearizable read in a system replicated across Mumbai and Virginia must either go to a single leader (one region pays 250 ms) or ask a majority of copies (quorums). A write must be acknowledged by a majority before it counts. That is where consensus enters.
Step 5: what you cannot have. When the network between two regions breaks (a partition), a system must choose: keep answering with possibly stale data, or refuse to answer until it can be sure. That choice is the practical content of the CAP theorem, and it is forced only during the partition. The rest of the time the trade is latency versus staleness, which the PACELC formulation makes explicit.
Why it works, with the numbers
Lag is measurable, so promises can be priced. If a replica is typically 20 ms behind and at worst 2 s, then "eventual" means a reader sees data 20 ms old almost always and 2 s old rarely. Read-your-writes costs one extra piece of state: the version number of the user's last write, carried in a cookie, and a replica that waits until it has applied that version:
extra read latency ≈ max(0, lag − time since the user's write), usually 0
Linearizable reads cost a round trip to a majority, so with three copies across regions 100 ms apart, every strong read costs about 100 ms more than a local one. The guarantee of each model is exactly its row in the table; the failure modes are the famous ones: a user who cannot find what they just wrote, a shopping cart that un-adds an item on refresh, a reply shown under the wrong post, and the silent one, a system that claims strong consistency but reads from a follower.
The trade-off you must say out loud
Strong consistency costs latency and availability; eventual consistency costs explaining to users why the comment vanished. Say, operation by operation, which promise you make and what it costs, and name the one place in the design that truly needs linearizability (usually money, inventory, or a lock). The interviewer's next question is "how do you give read-your-writes without routing everything to the leader?", and the version-cookie answer above is what they are listening for.
Where it shows up in the 100 Google problems
- Design a distributed key-value store: the tunable quorum sizes are a dial between eventual and strong, and you should say where you set it.
- Design a globally consistent database: the whole point is linearizable transactions across continents, paid for with Paxos and tightly synchronised clocks.
- Design Ticketmaster: seat availability can be eventual on the map but the hold itself must be linearizable.
- Design Google Pay: balances are read strongly before a transfer and eventually for the statement page.