Consistency models — in depth
The summary said "precise words for how out of date a read is allowed to be". This page makes them precise. It covers the six models in the order of what they cost, how to pick one per feature rather than per system, the mechanics of read-your-own-writes, why eventual consistency lets reads go backwards, what strong consistency costs on a good day, and the sentence that turns this from vocabulary into a design.
The six models, cheapest first
These are not a quality ladder where stronger is better. They are prices. Each one costs more than the one below it, and the skill is choosing the cheapest one that keeps users from seeing something wrong.
- Read-your-own-writes covers most user-facing complaints for a fraction of the cost of strong consistency.
- Monotonic reads is nearly free and removes a whole class of "the page keeps flickering" bugs.
- Causal consistency is usually what people mean when they say a system "feels" correct.
- Strong consistency is the one that adds a network round trip to every operation, whether or not anything is broken.
| Model | Promise | Cost |
|---|---|---|
| Eventual | Copies agree if writes stop | Reads can go backwards in time |
| Monotonic reads | You never see an older value than one you saw | Pin a user to one replica |
| Read-your-own-writes | You always see your own changes | Route that user's reads carefully |
| Consistent prefix | Causes appear before effects | Route related writes through one partition |
| Causal | Everything with a dependency appears in order | Track causality metadata |
| Strong (linearizable) | Any read anywhere sees the last confirmed write | A majority round trip, forever |
Eventual consistency lets reads go backwards
This is the property that surprises people, and it is legal rather than a bug. Under eventual consistency there is no promise about *when* copies agree, and no promise that a sequence of reads sees a non-decreasing view of the world.
Concretely: you load a page and see a comment count of 42, served by a replica that is caught up. You refresh and see 41, because the load balancer sent you to a replica that is three seconds behind. Nothing failed. Both answers were legal.
- The fix is monotonic reads: pin a user to one replica, usually by hashing their session id, so their view of history only moves forward.
- It costs almost nothing, and it means one slow replica affects a fixed set of users rather than randomly affecting everyone.
- A refresh that shows an older value looks like a bug to users, and it is hard to reproduce because it depends on which replica served each read.
- "Eventually consistent" without a number is a phrase, not a design. Say how long eventual is, and what the user sees in the meantime.
Read-your-own-writes, mechanically
This is often the highest-value guarantee in a user-facing product, because many "the app lost my change" reports are this: the write succeeded, and the next read hit a lagging replica. It is also far cheaper than making the whole system strongly consistent, because you only have to be careful about one user's reads rather than about everybody's.
There are three implementations, in increasing precision and increasing effort.
- Session pinning: after a user writes, mark their session and send their reads to the leader for a fixed window, say ten or thirty seconds. Two lines of code. The window is a guess, and leader read load rises with your most active users.
- Write position tokens: the write returns the log position it committed at, the client carries it, and a read waits for a replica that has reached at least that position. Precise, no guessed window, no unnecessary leader load. The catch is that reads can now block, which is a new latency risk.
- Client-side rendering: do not re-fetch at all. The client already has the value it just submitted, so render that. Free, and it only covers the exact thing they just wrote.
- A common pattern is the third where it fits and the first everywhere else, moving to the second when leader load becomes measurable.
What strong consistency costs
People choose strong consistency because it feels safe, and then are surprised that the system is slow when nothing is broken. That surprise comes from learning only the first half of PACELC.
Strong consistency means a write is not confirmed until a majority agrees, and often that a read consults a majority too. That is a round trip added to every operation, permanently. Inside one datacenter the network part is about half a millisecond, which is cheap. Across regions it is 80 milliseconds or more, and it applies on every good day, not just during failures.
- Strong consistency also means unavailability on the minority side of a network split. That is a choice you make on purpose, and for seats or balances it is the right one.
- It does not scale by adding nodes: a bigger majority is slower to convince.
- Use it on the specific operation that needs it, not on the whole system. The same product can have a strongly consistent checkout and an eventually consistent feed.
The last row is not a failure cost. It is what you pay on a completely healthy Tuesday, which is the half of PACELC that is easy to forget.
Choosing per feature: the sentence that scores
The move that turns this from vocabulary into design is going feature by feature, out loud, in one breath. It shows you treat these as prices rather than as qualities.
A worked version for a social commerce product: "The like count is eventually consistent. A second of lag is invisible and I am not spending a round trip on it. A user's own posts are read-your-own-writes, or they will think it failed and post again. Comments under a post are causally consistent, so nobody sees a reply above the thing it replies to. The stock check at checkout is strongly consistent, and I accept the extra latency there because selling the same item twice costs real money."
- Anything a human cannot tell is two seconds old: eventual.
- Anything the user just did: read-your-own-writes.
- Anything with a visible cause and effect: causal or consistent prefix.
- Anything contested and irreversible: strong, and say you accept the latency.
- Naming four features with four different answers is worth more than any definition you could recite.
The mistakes that cost points
These come up repeatedly and each one is avoidable with a single extra sentence.
- Saying "eventually consistent" with no number. How long is eventual, and what does the user see meanwhile?
- Applying one model to the whole system. Most products need several different answers, and saying so is what the interviewer is listening for.
- Forgetting that eventual consistency permits reads to go backwards, then being unable to explain the flickering count.
- Checking a value in application code and then writing. That gap is a race no consistency model closes for you.
- Confusing consistency with durability. A write can be strongly consistent and still lost if it was never fsynced.
- Confusing the C in ACID with the C in CAP. They are unrelated: the first means database constraints hold, the second means linearizability: every read sees the latest confirmed write, as if there were one copy.
Four features, four different answers
You are designing a marketplace. It has a product page with a view count, seller inventory, buyer reviews with replies, and a checkout. A junior engineer proposes making the whole system strongly consistent "to be safe". Your job is to price that proposal and then decide feature by feature.
- 1Price the blanket proposal
Strong consistency everywhere means a majority round trip on every read and write. The product page alone does about eight reads, so at about 2 ms of coordination each, run one after another, that is 16 ms added to a page nobody needed protected. If replicas ever span regions it becomes 640 ms and the product is unusable. It also means the page goes down entirely on the minority side of a network split, including the parts that could have been served perfectly well. The proposal was not free, and for most of the page it protected nothing.
- 2View count: eventual
Nobody can tell a view count is two seconds old, and nobody makes a decision from it. Eventual consistency, sharded counters, cached total refreshed every few seconds. The cost is that the number can briefly go backwards on refresh, which I remove cheaply by pinning a user to one replica: monotonic reads for almost nothing.
- 3Seller inventory: two answers, not one
This is the interesting one, because the same data needs different guarantees in different places. The "3 left" badge on the browse page can be eventually consistent and slightly wrong. The worst case is mild disappointment. The stock check inside checkout must be strongly consistent, and specifically must be a conditional update inside the transaction that reserves the item, not a read followed by a decision. Same field, two guarantees, chosen by what being wrong costs at that moment.
- 4Reviews and replies: causal
A reply appearing above the review it answers is not slow, it is nonsense, and users report it as a bug. But full strong consistency is not needed. A review taking two seconds to appear is fine; what matters is it appears in the right order relative to its parent. So route all writes for one review thread through one partition, and ordering comes free, with no cross-partition coordination.
- 5The seller's own listing: read-your-own-writes
A seller edits a price and reloads. If a lagging replica serves that read, they see the old price, assume it failed, and edit again, which creates a support ticket and possibly a duplicate. Pin their reads to the leader for ten seconds after any write. This is the cheapest fix on the page, and it prevents the complaint sellers are most likely to raise.
- 6Say the whole thing in one breath
"Counts eventual with monotonic reads. Browse-page stock eventual, checkout stock strongly consistent via a conditional update. Review threads causally ordered by partitioning on thread id. A seller's own edits read-your-own-writes for ten seconds. Four features, four prices, each chosen by what being wrong costs."