Consistency Models
Linearizable, sequential, causal, eventual — and what each one actually buys you
Consistency Models
"Strong consistency" is the most overloaded phrase in distributed systems. Two engineers can both swear their system is "consistent" and mean wildly different things. The vocabulary in this page exists to make those conversations precise.
A consistency model is a contract between the storage system and the application: given concurrent operations, which results are allowed? The model is not about whether the system is "correct" — every model is internally correct. The question is which model your application's correctness actually depends on, and whether you have correctly identified it.
The Hierarchy
Consistency models form a partial order. Stronger models forbid more behaviors, which means they admit fewer optimizations and are usually more expensive.
Linearizable ← strongest, most expensive
│
▼
Sequential
│
▼
Causal
│
▼
Read-your-writes / monotonic
│
▼
Eventual ← weakest, cheapestEach level allows everything the level below it allows, plus more.
Linearizability
Also called atomic consistency or strong consistency in casual usage.
Definition: every operation appears to take effect at some instant between its invocation and its completion, and that order is consistent with real time. After a write completes, every later read (in wall-clock time) sees its effect.
Intuition: the system behaves as if it were a single machine processing one request at a time. There is a single global timeline, and every client sees it.
Wall-clock time ────────────────────────────▶
Client A: [─ write x=1 ─]
Client B: [─ read x ─] returns 1 ✓
Client C: [─ read x ─] returns 1 ✓Cost: in CAP terms, this is the C. It requires coordination on every write — typically consensus (Raft / Paxos) or a single leader. Reads either go through the leader or use read leases.
Use when: distributed locks, leader election, unique-ID allocation, configuration that must be globally agreed, any "is it safe to do X now?" question.
Don't use when: you can satisfy your requirement with a weaker model. Linearizability has a real latency tax — Spanner's TrueTime waits, Raft's quorum round trips. Many problems people reach for it for are actually causal-consistency problems.
Sequential Consistency
Definition: there exists some total order of operations consistent with each client's program order, and every client sees that same order. The order does not need to match real time.
The difference from linearizability: if Client A writes at 10:00:00 and Client B reads at 10:00:05, sequential consistency permits the read to return the old value, as long as B never sees the new one after an old one.
Real time: Client A writes x=1 ────▶ Client B reads x=0
(perfectly legal under sequential consistency
if B's session has not yet observed the write)Use: rarely a useful target on its own. Mostly a stepping stone in textbooks. Real systems usually pick either linearizable (for the strong guarantees) or causal+session (for the weaker but cheaper).
Causal Consistency
Definition: writes that are causally related must be seen by all processes in the same order. Concurrent writes (no causal relation) can be seen in different orders by different processes.
"Causally related" is defined by Lamport's happens-before relation (see Logical Clocks):
- Operations from the same client in program order are causally ordered.
- A read that returns value
vis causally after the write ofv. - Causality is transitive.
Causally related (must be ordered):
Alice posts "Lost my phone"
└─▶ Alice posts "Found it!" (depends on first post existing)
└─▶ Bob comments on "Found it!"
Concurrent (any order allowed):
Alice posts a recipe
Carol posts a holiday photo ← unrelated, can appear in any orderCost: much cheaper than linearizable. No global coordination needed; only causal metadata (vector clocks, dependency lists) attached to writes.
Use when: social feeds, comment threads, collaborative editing — anywhere "this depends on that" matters but global order does not. COPS, Eiger, and similar academic systems target this; many CRDT-based systems achieve it.
Session Guarantees
These are properties weaker than causal but more useful than raw eventual consistency. A session is one client's logical thread.
| Guarantee | Promise |
|---|---|
| Read-your-writes | After you write x=1, your subsequent reads see 1 (or newer). You do not see your own writes regressing. |
| Monotonic reads | If you read v, no later read in your session returns a value older than v. |
| Monotonic writes | Your writes are applied in the order you submitted them. |
| Writes-follow-reads | If you read v and then write w, every replica that has w also has v. |
These four together are sometimes called PRAM (Pipelined RAM) consistency. They cost almost nothing to implement (route a session's traffic to the same replica, or attach a per-session vector) and remove the most jarring user-visible anomalies of eventual consistency.
Use: almost always. Even AP systems should give clients at least read-your-writes; not doing so creates UI bugs ("I just clicked save and the form is blank").
Eventual Consistency
Definition: if writes stop, all replicas eventually converge to the same value. Until then, anything goes.
Eventual consistency is a liveness property — a promise about the limit, not the journey. Two reads against an eventually consistent store can return arbitrary stale or out-of-order values until convergence.
Use when: the workload is genuinely commutative and conflict-free (counters with CRDTs, append-only logs), or staleness is fine (analytics, recommendation caches).
Don't use when: users will notice. "Eventual" can mean hundreds of milliseconds to minutes during replication delay; that is a long time to see a stale balance.
Snapshot Isolation, Serializable, and the Transaction Models
The hierarchy above is for single-object operations. Once you bring in multi-object transactions, a parallel set of models applies:
- Serializable — transactions appear to execute in some serial order. (No real-time bound, unlike strict serializable / linearizable.)
- Strict serializable — serializable and the serial order respects real time. The transactional equivalent of linearizable.
- Snapshot isolation — every transaction reads from a consistent snapshot; writes commit if no other transaction wrote the same key. Vulnerable to write skew.
- Read committed, repeatable read, etc. — SQL standard levels, mostly weaker.
These belong in a database-theory page (see database/transactions/isolation-levels); they are mentioned here only because people confuse them with the single-object models above.
How to Pick
Ask, in order:
- Do I need a total real-time order? (Locks, leader election, "did this happen before that?") → linearizable.
- Do I need transactions across multiple objects? → serializable / strict serializable.
- Do causal dependencies matter, but not global order? → causal + session guarantees.
- Can users tolerate temporarily seeing my own writes go missing? Almost always no → at least read-your-writes.
- None of the above? → eventual is fine, and it is the cheapest.
The mistake is to start at the top of the list and stop reading. Most application requirements bottom out at causal + session, not linearizable.
Further Reading
- Herlihy & Wing, Linearizability: A Correctness Condition for Concurrent Objects (1990) — the original definition.
- Lamport, Time, Clocks, and the Ordering of Events in a Distributed System (1978) — happens-before, the foundation of causality.
- Terry et al., Session Guarantees for Weakly Consistent Replicated Data (1994) — the Bayou paper that named the four session models.
- Bailis & Ghodsi, Eventual Consistency Today: Limitations, Extensions, and Beyond (2013) — survey.
- Kleppmann, Designing Data-Intensive Applications, Chapter 9 — the most accessible modern treatment.
- Jepsen.io consistency models page — the canonical reference diagram.
Pre-commit Checklist
- When I said "strongly consistent," did I mean linearizable, serializable, or something else?
- For each user-visible read, do I provide at least read-your-writes? If not, what is the UX cost?
- For multi-object operations, am I conflating per-object consistency with transactional isolation?
- Did I choose the weakest model that meets the requirement, or the strongest model I felt safe with?