Consistency Models Reference
Linearizability to eventual, serializable to read committed, CAP to PACELC — and what each real database actually gives you by default.
Last reviewed ·revision 1·first published
This is a living document. It is revised when the underlying numbers or practice change, not on a publishing schedule.
Show revision historyHide revision history
First publication. Separates the consistency and isolation axes, states CAP precisely, and tabulates default versus strongest guarantees for twelve production systems.

Consistency models (linearizable, causal, eventual) govern which reads replicas may return; isolation levels (serializable, snapshot, read committed) govern which transaction interleavings are observable. They are orthogonal — strict serializability is both. CAP applies only during a partition; PACELC's else-clause, latency versus consistency, governs normal operation and matters far more.
Almost every argument about consistency is really two arguments wearing one word. Before the table, separate them:
- Consistency models (linearizability, causal, eventual) answer: given concurrent operations across replicas, which reads am I allowed to see? This is the distributed-systems axis, and it is what the C in CAP means.
- Isolation levels (serializable, snapshot, read committed) answer: given concurrent transactions, which interleavings am I allowed to observe? This is the database axis, and it is what the I in ACID means.
They are orthogonal. A system can be serializable and not linearizable (snapshot-based, reads from a stale-but-consistent point). It can be linearizable and not serializable (single-key register with no transactions). Strict serializability is the corner where you have both, and it is the only model that behaves the way most engineers assume their database already behaves.
The C in ACID is neither of these. It means "your integrity constraints hold," which is your problem, not the database's.
The consistency ladder
Strongest at the top. Each level permits everything the levels below permit.
| Model | Guarantee | Cost |
|---|---|---|
| Strict serializability | Transactions appear to execute one at a time, in an order consistent with real time | Coordination on every write; a global time source or consensus |
| Linearizability | Every single-object operation appears to take effect at one instant between invocation and response | A round trip to a quorum, per operation |
| Sequential consistency | All nodes see the same order of operations; that order need not match real time | Global agreement on order, no real-time constraint |
| Causal consistency | Operations that are causally related are seen in that order everywhere; concurrent operations may be seen in any order | Metadata (vector clocks / dependency tracking); no coordination |
| Session guarantees | Read-your-writes, monotonic reads, monotonic writes, writes-follow-reads — per client only | Sticky routing or a session token |
| Eventual consistency | Replicas converge if writes stop. Nothing is promised before then | None |
The practical middle. Causal consistency plus session guarantees — often marketed as causal+ — is the highest level obtainable without coordination, and it removes the anomalies users actually notice: your own comment vanishing, a reply appearing before the message, a timeline going backwards. Most applications that "need strong consistency" need this and a strongly consistent read on two or three specific operations.
The session guarantees, individually
Worth knowing separately, because you usually need only one:
- Read-your-writes — you see your own write. The fix for "I saved it and it's not there."
- Monotonic reads — you never see time go backwards. The fix for a value that appears, disappears, reappears as you hit different replicas.
- Monotonic writes — your writes apply in the order you issued them.
- Writes-follow-reads — if you read a value and then write, your write is ordered after what you read. The fix for a reply that lands before the thing it replies to.
The isolation ladder and its anomalies
| Level | Dirty read | Non-repeatable read | Phantom | Write skew | Lost update |
|---|---|---|---|---|---|
| Read uncommitted | ✅ possible | ✅ | ✅ | ✅ | ✅ |
| Read committed | ❌ prevented | ✅ | ✅ | ✅ | ✅ |
| Repeatable read (ANSI) | ❌ | ❌ | ✅ | ✅ | ✅ |
| Snapshot isolation | ❌ | ❌ | ❌ | ✅ | ❌ |
| Serializable | ❌ | ❌ | ❌ | ❌ | ❌ |
Write skew is the one that bites. Snapshot isolation prevents everything the ANSI levels name, which is why it is widely sold as "repeatable read" or even mislabelled serializable. It does not prevent two transactions from each reading a shared invariant, each deciding independently that their write is safe, and together violating it. The canonical case: two doctors on call, each checks that the other is still on call, each signs off, and now the hospital has nobody. No individual transaction did anything wrong.
If a constraint spans rows and is enforced in application code after a read, you need SERIALIZABLE or an explicit lock. Nothing weaker is safe, and the failure is silent.
CAP, stated precisely
CAP is narrower than its reputation. The theorem says: during a network partition, a system cannot provide both linearizability and total availability. That is the whole claim.
What it does not say:
- It is not a menu of three from which you choose two. Partition tolerance is not optional — networks partition whether or not you consented.
- The C is linearizability specifically, not "consistency" generally. Causal consistency is available during a partition.
- The A is total availability — every non-failing node answers every request. Degraded, partial, or read-only availability is outside the model.
- It says nothing about ordinary operation, which is where your system spends more than 99.9% of its life.
PACELC is the more useful formulation: if there is a Partition, choose Availability or Consistency; Else, choose Latency or Consistency. The second clause is the one that governs your day. Every quorum read is latency spent on consistency you may not need, on a network that is working fine.
What real systems actually give you
Defaults matter more than capabilities, because the default is what you shipped.
| System | Default read | Strongest available | The thing that surprises people |
|---|---|---|---|
| PostgreSQL (single primary) | Read Committed | Serializable (SSI) | Async replicas serve arbitrarily stale reads; routing reads to a replica silently drops you to eventual consistency |
| MySQL / InnoDB | Repeatable Read | Serializable | Its Repeatable Read is snapshot-based and permits write skew; SELECT ... FOR UPDATE reads the latest row, not your snapshot |
| Amazon Aurora | Read Committed | Serializable (writer) | Reader endpoints lag the writer by milliseconds — small, non-zero, and enough to break read-your-writes |
| Google Spanner | Strict serializability | Strict serializability | The strongest commercially available model, paid for in commit-wait against TrueTime's uncertainty interval |
| CockroachDB | Serializable | Serializable | Serializable by default and linearizable per key; contention surfaces as retryable errors your client must handle |
| DynamoDB | Eventually consistent | Strongly consistent read (per item); serializable transactions | Strongly consistent reads cost double and are unavailable on global secondary indexes |
| Apache Cassandra | Tunable (ONE by default in most drivers) | Linearizable single-partition via lightweight transactions (Paxos) | R + W > RF gives quorum overlap, not linearizability; conflict resolution is last-write-wins by timestamp, so clock skew silently deletes data |
| MongoDB | readConcern: local | linearizable reads; causal-consistent sessions; multi-document transactions | Defaults are not majority-read; a primary failover can roll back writes an application already observed |
| Redis | Linearizable on one node | — | Replication is asynchronous; a failover loses acknowledged writes. WAIT reduces the window, it does not close it |
| etcd / ZooKeeper | Linearizable writes | Linearizable reads | ZooKeeper reads are sequentially consistent, not linearizable, unless preceded by sync() |
| Amazon S3 | Strong read-after-write | Strong read-after-write | True since December 2020; guidance written before that date is stale, and much of it is still online |
| Apache Kafka | Per-partition ordering | Idempotent producer + transactions | There is no ordering across partitions, so any invariant spanning two keys needs them in the same partition |
Choosing, in four rules
- Money, inventory, uniqueness, and anything with a legal consequence — serializable, single-region, coordinated. Do not be clever. The throughput you save is worth less than one reconciliation incident.
- Anything a single user observes about their own data — session guarantees. Sticky routing plus read-your-writes covers nearly all perceived-correctness complaints at close to zero cost.
- Feeds, counts, recommendations, aggregates, search — eventual, and say so in the UI. A view count that is 30 seconds stale is not a bug; a spinner while you wait for a quorum is.
- Cross-region writes on the request path — decide the model before you choose the region topology, not after. Strict serializability across continents means a minimum write latency set by the speed of light — a floor of roughly 65 ms US coast-to-coast and 150 ms transatlantic, no matter what you buy.
The three mistakes
Assuming your default is strong. Most defaults are Read Committed or eventual. Nearly everyone who says "we use Postgres, so we're consistent" is running Read Committed with replica reads.
Enforcing invariants in application code under snapshot isolation. Read-check-write across rows is exactly the write-skew shape. It passes every test that runs one transaction at a time.
Using last-write-wins as conflict resolution. LWW is data loss with a timestamp attached, and the timestamp comes from a clock you do not control. If two writes can legitimately conflict, you need CRDTs, application-level merge, or single-writer partitioning.
Sources
- Consistency Models (survey and hierarchy) — Jepsen (verified )
- A Critique of ANSI SQL Isolation Levels — Berenson et al., Microsoft Research (verified )
- Consistency Tradeoffs in Modern Distributed Database System Design (PACELC) — Daniel Abadi, University of Maryland (verified )
- Spanner: TrueTime and external consistency — Google Cloud (verified )
- Amazon S3 strong read-after-write consistency — AWS (verified )
Frequently asked
What is the difference between linearizability and serializability?
Linearizability is a guarantee about single objects: every operation appears to take effect at one instant between its invocation and its response, consistent with real time. Serializability is a guarantee about transactions: some serial order exists that explains the outcome, with no requirement that it match real time. Strict serializability is both, and it is the model most engineers assume they already have.
Does snapshot isolation prevent all anomalies?
No. Snapshot isolation prevents dirty reads, non-repeatable reads, phantoms and lost updates, but permits write skew — two transactions each read a shared invariant, each independently decide their write is safe, and together violate it. If you enforce a multi-row constraint in application code after a read, you need serializable isolation or an explicit lock.
What does the CAP theorem actually say?
That during a network partition, a system cannot be both linearizable and totally available. It is not a choose-two-of-three menu — partition tolerance is not optional. It says nothing about behaviour when the network is healthy, which is where systems spend virtually all of their time. PACELC extends it: else, choose latency or consistency.
Is PostgreSQL strongly consistent?
A single primary is linearizable for its own reads and writes, but the default isolation level is Read Committed, not Serializable, and asynchronous replicas serve arbitrarily stale data. Routing reads to a replica for scale silently moves the application to eventual consistency, which is where most surprising behaviour originates.
Does R + W > RF give linearizability in Cassandra?
No. Quorum overlap guarantees that a read set intersects the last write set, which is weaker than linearizability — concurrent operations, failed writes and read repair can still produce non-linearizable histories. Linearizable single-partition operations require lightweight transactions, which run Paxos and cost roughly four round trips.
When is eventual consistency the right choice?
When staleness is invisible or harmless to the user and coordination cost is not: feeds, view counts, recommendations, search indexes, aggregates and analytics. Reach for session guarantees rather than full strong consistency when the concern is a user seeing their own action, and reserve serializable for money, inventory, uniqueness and anything with a legal consequence.