Lesson 24 · Consistency models · Module 2
The Consistency Map
Two engineers say "eventually consistent" and mean guarantees that differ by an enormous margin — one of them forbids reads that go backwards in time, the other forbids nothing at all. The models have precise names, they sit in a known order, and the order tells you what each one costs.
The win in this lesson: you will be able to take any guarantee you meet — in a vendor's documentation, in a design review, in your own service — and place it on one map, say what it forbids, and say whether it can still answer requests when the network splits.
1. The word that means nothing on its own
"Eventually consistent" is not a model. It is the residue left when you delete every model. To say something useful you need the actual vocabulary, and the vocabulary is unusually well defined — each model is a rule about which histories a system is allowed to produce.
"A consistency model is a safety property which declares what a system can do. Formally, a consistency model defines a set of histories that a system can legally execute."
Jepsen, Consistency
Which gives you the trick that makes the whole area tractable. Do not try to remember what a model promises — promises are vague and marketing owns them. Remember what it forbids.
"Consistency models are often defined in terms of proscribed phenomena: specific patterns of operations."
Jepsen, Consistency
When someone tells you their store is consistent, the useful reply is never "how consistent?" It is "name a history it will never produce". A model that cannot answer that is not a model, and a system that cannot answer it has not chosen one.
2. The models, by what each one forbids
Linearizable — the strongest single-object model
"Linearizability is one of the strongest single-object consistency models, and implies that every operation appears to take place atomically, in some order, consistent with the real-time ordering of those operations: e.g., if operation A completes before operation B begins, then B should logically take effect after A."
Jepsen, Linearizability
It forbids any read that misses an already-completed write, from any process, ever. That "real-time" clause is the expensive part: it binds the system to wall-clock ordering that it cannot observe locally, which is why it needs agreement between nodes before it can answer.
Sequential — one order, but not necessarily yours
Drop the real-time requirement and keep the single order, and you have sequential consistency. Everybody agrees on the sequence; nobody promises the sequence tracks the clock.
"A process in a sequentially consistent system may be far ahead of, or behind, other processes. For instance, they may read arbitrarily stale state. However, once a process A has observed some operation from process B, it can never observe a state prior to B."
Jepsen, Sequential Consistency
So it forbids two processes disagreeing about the order of any two writes. It permits the whole system to be minutes behind.
Causal — order only where order was possible
"Causal consistency captures the notion that causally-related operations should appear in the same order on all processes—though processes may disagree about the order of causally independent operations."
Jepsen, Causal Consistency
Jepsen's example is a three-person chat, and it is worth having in your head because it shows exactly which disagreement is legal and which is not:
"Causal consistency allows Attiya to observe “lunch?”, “yes”, “no”; and Barbarella to observe “lunch?”, “no”, “yes”. […] However, no participant ever observes “yes” or “no” prior to the question “lunch?”."
Jepsen, Causal Consistency
It forbids an effect being visible before its cause. Two answers may arrive in either order. Neither may arrive before the question.
The session guarantees — four small promises to one client
Below causal sit four guarantees that constrain only what one process sees. They are weak, cheap, and they are the ones you will actually be offered.
"Read your writes (also known as read my writes) requires that if a process performs a write w, and that same process performs a subsequent read r, then r must observe w’s effects."
Jepsen, Read Your Writes
And the limit, which is the half people forget:
"Note that read your writes does not apply to operations performed by different processes. There is no guarantee, for instance, that if process 1 writes a value successfully, that process 2 will subsequently observe that write."
Jepsen, Read Your Writes
The other three:
- Monotonic reads — "if a process performs read r1, then r2, then r2 cannot observe a state prior to the writes which were reflected in r1; intuitively, reads cannot go backwards" (Monotonic Reads).
- Monotonic writes — "if a process performs write w1, then w2, then all processes observe w1 before w2" (Monotonic Writes).
- Writes follow reads — "if a process reads a value v, which came from a write w1, and later performs write w2, then w2 must be visible after w1. Once you’ve read something, you can’t change that read’s past" (Writes Follow Reads).
Three of those four bundle into one named model, which saves you a lot of words:
"PRAM is exactly equivalent to read your writes, monotonic writes, and monotonic reads."
Jepsen, PRAM
Put in a table
| Model | What it forbids | Available under a partition? |
|---|---|---|
| Linearizable | Any read missing a write that already completed, in real time | No — some or all nodes stop |
| Sequential | Two processes disagreeing on the order of any two operations | No — some or all nodes stop |
| Causal | Seeing an effect before the cause it depends on | Sticky only — client must not move server |
| PRAM | Any reordering of the operations a single process issued | Sticky only |
| Read your writes | Your own later read missing your own earlier write | Sticky only |
| Monotonic reads | Your reads going backwards to an earlier state | Yes — totally available |
| Monotonic writes | Your second write landing anywhere before your first | Yes — totally available |
| Writes follow reads | A write becoming visible before the write it replied to | Yes — totally available |
| Eventual | Nothing about any read you can make today | Yes — nothing to coordinate |
3. The lattice
These are not nine unrelated options. They are ordered, and the order has an exact meaning:
"When we say that model x implies y, we mean that for every history where x holds, y does too; x is “stronger” than y."
Jepsen, Consistency Models
"For single-object models, strict serializable implies linearizable, which implies sequential, which implies causal. Causal implies writes follow reads and PRAM."
Jepsen, Consistency Models
4. One history, two verdicts
A model is only real to you once you can look at a history and say which models it breaks. Two examples, and both are things your system probably does today.
Monotonic reads satisfied, read your writes violated
Causal satisfied, sequential violated
5. Which models survive a partition
Now the property that decides architecture. The line runs through the lattice in one place, and Jepsen states it in one sentence:
"All models at or stronger than cursor stability, snapshot isolation, and sequential cannot be totally available in asynchronous networks. All models at or stronger than read your writes can be at most sticky available. Weaker models (of those listed here) can be totally available."
Jepsen, Consistency Models
Three bands, and each has a concrete operational meaning.
Not available at all
"This model cannot be totally or sticky available; in the event of a network partition, some or all nodes will be unable to make progress."
Jepsen, Linearizability — the identical sentence appears on Sequential Consistency
Not "gets slower". Unable to make progress. A minority partition holding a linearizable store must refuse your request, because the only honest alternative is to answer from state it cannot prove is current.
Sticky available
"Causal consistency is sticky available: even in the presence of network partitions, every client connected to a non-faulty node can make progress. However, clients must stick to the same server."
Jepsen, Causal Consistency
Read your writes carries the same caveat, phrased as an operational rule:
"Read your writes is sticky available: if a network partition occurs, every node can make progress, so long as clients never change which server they talk to."
Jepsen, Read Your Writes
Sticky availability is a guarantee you can lose by accident. A retry that lands on a different node, a connection pool that reopens elsewhere, a failover, a client that reconnects through a different edge — each of them silently drops you out of the band you thought you were in. Nothing errors. The guarantee just stops applying. This is the same lesson as Lesson 04 from the other direction: a retry is not a free repeat of a request, it is a new request with different properties.
Totally available
Monotonic reads, monotonic writes and writes follow reads each carry the strongest availability claim on the map — "even during a network partition, all nodes can make progress" (Monotonic Reads), and "Every node can make progress regardless of network partitions" (Writes Follow Reads).
And Jepsen spells out the exact trade you make to get there:
"If you need total availability, you’ll have to give up causal (and read-your-writes), but can still obtain writes follow reads, monotonic reads, and monotonic writes."
Jepsen, Causal Consistency
Why stronger always costs coordination
The pattern in the lattice is not a coincidence. Every model above the line constrains what different processes may see relative to each other. A node cannot satisfy a constraint about other nodes' observations using only local state — it has to hear from them first. That message is the cost, and a partition is precisely the condition in which the message does not arrive.
Everything below the line constrains only one session against itself. A single node can enforce that alone, out of what it already knows, which is why a partition changes nothing.
6. Where this still leaks
Three residual risks, and the first two are how teams get this wrong in practice.
- A system is not on one point of the map. Stores routinely offer different models per operation — a consistency level chosen per query, a linearizable compare-and-set alongside eventually consistent reads, a transactional path beside a fast path. "Which model does it give?" is the wrong question; "which model does this call give?" is the right one, and the answer can change when someone edits a config.
- Guarantees do not compose across objects. Linearizability is a single-object model — "the scope of 'an object' varies. Some systems provide linearizability on individual keys in a key-value store" (Linearizability). Two linearizable keys do not make a linearizable pair of keys, and two services each keeping causal order do not give you causal order across the pair. Every hop through a queue, a cache or a second datastore is a place where the guarantee ends and nobody writes it down.
- The map is what a model permits, not what your vendor implements. A model is a claim about every history the system can produce; the only way to know is to generate histories and check them, which is the entire reason Jepsen exists. Documentation describes the intent.
7. Check yourself
8. Back to your world
Take the last design you shipped that reads from anywhere other than the place it writes. A cache, a replica, a search index, a second service. Write down the strongest model it actually provides, then write down which of the nine rows above your product requirement needs. They are rarely the same row, and the gap is where your next incident lives.
The two questions to carry: name one history this system will never produce, and what happens to that promise when the network splits and my client reconnects somewhere else? If the second answer is "nothing changes", you are below the line and you are safe. If it is "I do not know", you are sticky available and you are one failover away from finding out.