05 / 20
Topics / 05

Consistency models

A consistency model is the contract a replicated store offers a reader: given concurrent writes across many replicas, which values may a read return, and in what order? The models form a hierarchy. Stronger models forbid more anomalies and cost more coordination. Weaker models allow more anomalies and run faster, closer to users, and through partitions. Knowing exactly where a system sits is the difference between a correct design and a subtle data-loss bug that only shows up under load.


Consistency is not isolation

Two words that sound alike and mean different things. Isolation (the I in ACID) is about concurrent transactions: do they interleave as if they ran one at a time? That is the serializability axis. Consistency, in the distributed sense, is about a single object replicated across nodes: when does a read reflect a write? A database can be Serializable but not linearizable, or linearizable on single objects but not serializable across them. The gold standard that combines both is strict serializability — serializable transactions whose order also respects real time.

Two axes, one matrix. Isolation runs from Read Uncommitted up to Serializable. Consistency runs from eventual up to linearizable. They are orthogonal. Spanner is strict serializable (top-right). A single-node Postgres with Serializable isolation is serializable but, with read replicas, only eventually consistent.

Linearizability — the strongest single-object model

Linearizability (Herlihy & Wing, 1990) is the illusion that there is exactly one copy of the data and every operation takes effect atomically at some instant between its invocation and its response. Once a write completes, every later read — by any client — must see that write or a newer one. There are no stale reads.

The key word is real time. If operation A finishes before operation B begins (in wall-clock order), the linearized order must put A before B. This is what makes linearizability composable: a system built from linearizable parts is itself linearizable.

The cost is coordination. Every linearizable read must confirm it is not serving a stale value, which means a round-trip to a quorum or the leader. Linearizable systems: etcd, ZooKeeper (for writes and sync reads), single-key operations in Spanner, a compare-and-swap register backed by Raft.

Sequential consistency — order without real time

Sequential consistency (Lamport, 1979) keeps the requirement that all clients see operations in some single total order, and that each client's own operations appear in program order — but drops the real-time constraint. Two operations on different clients can be reordered even if one finished before the other started, as long as everyone agrees on the same ordering.

In practice the gap matters: under sequential consistency you can write a value, a colleague reads the store a second later, and legitimately sees the old value, because the system is allowed to place their read "before" your write in the agreed order. CPU memory models are the most familiar example — without barriers, hardware gives you something near sequential, not linearizable, consistency.

Causal consistency — the sweet spot

Causal consistency preserves the happens-before relation: if event A could have influenced event B (A wrote a value B read, or A and B are on the same client in order), then every node observes A before B. Operations with no causal link are concurrent and may be seen in different orders by different nodes.

This is the strongest model achievable while staying available under network partitions (the result is from Mahajan, Alvisi & Dahlin, and reinforced by the COPS and Bolt-on causal work). It rules out the anomalies that confuse users — you never see a reply before the message it answers — without paying for global agreement.

  • Read-your-writes. You always see your own prior writes.
  • Monotonic reads. Once you see a value, you never see an older one.
  • Monotonic writes. Your writes are applied in the order you issued them.
  • Writes-follow-reads. A write you make after reading X is ordered after X everywhere.

Those four "session guarantees" (Terry et al, Bayou) together compose into causal consistency. Implementations track dependencies with vector clocks or version vectors.

Eventual consistency — convergence, eventually

The weakest useful model: if writes stop, all replicas eventually converge to the same value. It says nothing about when, nothing about intermediate reads, and nothing about which concurrent write wins unless you add a rule (last-write-wins, a merge function, or a CRDT). Dynamo, Cassandra in its default mode, and DNS are eventually consistent.

Eventual consistency is not "wrong" — it is the price of staying available during a partition, which is exactly the AP corner of CAP. The danger is treating it as if it were stronger. Naive last-write-wins on free-form data silently drops concurrent writes. The fix is to make convergence a deliberate design choice, not an accident.

The hierarchy at a glance

ModelGuaranteeAvailable under partition?
Strict serializableSerializable transactions + real-time orderNo
LinearizableSingle-object real-time order, no stale readsNo
SequentialOne agreed total order, program order per clientNo
CausalHappens-before preserved; concurrent ops may differYes
EventualReplicas converge once writes stopYes

Stronger models imply weaker ones: every linearizable system is sequentially consistent, every sequentially consistent system is causal, and so on down. Pick the weakest model that still makes your application correct — it is the cheapest one that works.

Common misunderstandings

  • "Strong consistency means ACID." No. ACID consistency means constraints hold (foreign keys, check constraints). Distributed "strong consistency" usually means linearizable. Same word, unrelated guarantees.
  • "Linearizable and serializable are the same." Linearizable is about single objects and real time. Serializable is about multi-object transactions and any equivalent serial order. You need both — strict serializability — for the strongest guarantee.
  • "Quorum reads are linearizable." Only with care. Dynamo-style W + R > N guarantees overlap, but without read-repair and a last-writer rule it can still return stale or conflicting values. Linearizability needs a synchronization point, not just overlapping quorums.
  • "Eventual consistency is good enough by default." Only if you have defined the convergence rule. Otherwise you have undefined behaviour that happens to look fine in testing and loses data in production.

Further reading

Found this useful?