System designCore9 min

Consistency models

Copies of your data lag behind each other. A consistency model is the exact promise about what a read may show while they do. Learn the ladder from linearizable to eventual, and which rung each feature needs.

1 · The word

Three meanings of "consistency", and one false friend

Ask three engineers what "consistent" means and you get three correct answers. In ACID, the C means every transaction leaves the database obeying its rules: no negative balance, no duplicate username. In the CAP theorem, C means linearizability, defined below. Consistent hashing is about which server stores a key and has nothing to do with either. This article is about a third meaning, replica consistency: what the copies of one piece of data may show a reader.

Term

What it promises

Where it lives

ACID consistency

Every transaction keeps the invariants

Transactions & isolation levels

CAP consistency

Linearizability, the strongest model here

CAP & PACELC

Replica consistency

What each copy may show a reader

This article

Consistent hashing

Which server owns a key; unrelated

Consistent hashing

Why is there a question at all? Because the shop this article follows keeps one copy of its database in London and another in New York, and every change made in one city takes time to reach the other. During that gap the copies disagree, and whoever reads the wrong one sees the past.

London customerLondon copyNew York copyNew York customerwrites, readscopy, some ms laterreadsLondon customerLondon copyNew York copyNew York customerwrites, readscopy, some ms laterreads

Two copies, one lagging. Every model below is a rule about what the New York reader may see while the copy is on its way. How the copy travels is Database replication; here only the promise matters.

2 · The strongest

Linearizable: as if there were one copy

Linearizable is the promise that the system behaves as if there were a single copy, and every operation took effect at one instant between the moment it started and the moment it returned. The instant is what matters: once a write has returned, every read that starts afterward, from any client in any city, must see it. This is what people usually mean by strong consistency, and it is the C in CAP.

The laptop already saw order #881, so the phone's later read must see it too. A read that returns the new value, followed by one that returns the old, is exactly what linearizability forbids. The lagging New York copy caused it.

The real-time requirement is the expensive part. The replica that answers must know it holds the latest write, so either every read goes to one leader or the replicas coordinate before answering. Both cost round trips, and neither works while the cities cannot talk. That bill is CAP & PACELC.

Guarantee

About

Respects real time?

Linearizable

One operation on one object: a read, a write, a compare-and-set

Yes: what finished before another started comes first

Serializable

Whole transactions over many objects, as if run one after another

No: any order will do, even one that puts an older commit after a newer one

Strict serializable

Both at once

Yes

Databases advertise serializable as their strongest isolation level, and readers assume it implies freshness. It does not. Serializability only says transactions appear to run one at a time in some order, and that order may place a transaction that committed a minute ago after yours. Isolation levels have their own page (Transactions & isolation levels). The row to remember: serializable plus linearizable is strict serializable.

3 · Relaxing it

Sequential drops the clock, causal drops the shared order

Linearizableone order, real timeSequentialone order, no clockCausalrelated ops in orderSession guaranteespromises to one clientEventualcopies converge, somedaydrop real timedrop the total orderkeep only your owndrop even that

Each step down removes a promise and buys latency and availability. Everything at or above sequential must stop answering during a partition; causal and the session guarantees can keep answering if each client sticks to one replica.

Sequential consistency keeps one half of linearizability and drops the other. Everyone still sees the same single order of operations, and each client's own operations keep their program order, but the shared order need not match the clock. A review posted in London at 12:00:00 and one posted in New York at 12:00:05 may be shown to everyone, in both cities, with New York's first. Nobody can tell, unless they compare wristwatches.

Causal consistency drops the shared order too and keeps only the order that matters: if one operation could have influenced another, everyone sees them in that order. It is the happens-before relation from Time, clocks & ordering, turned into a promise. A seller reads a question on a product page and writes the answer, so the answer depends on the question: no copy may show the answer without it. Two unrelated reviews, though, may appear in different orders in the two cities. That is what causal gives up.

Causal is a special rung. It has been proved that a strengthening of it, real-time causal, is the strongest model a system can offer while staying available to every client and still converging. A common practical version is causal+: causal order plus a rule that makes conflicting writes converge. Anything stronger means coordinating across the ocean.

4 · The weakest

Eventual consistency promises convergence and nothing else

Eventual consistency is the weakest promise still worth a name. The definition: if no new updates are made to the object, eventually all accesses will return the last updated value. Read it twice. It promises convergence and only convergence: no bound on how long, and nothing about what a read returns before then. Put bluntly, it only says something good will eventually happen. It never says something bad will not.

You might expect

What eventual consistency actually says

Reads show recent data

Any value ever written may come back until the copies converge

Reads never go backwards

A read may show the new value, then the old one

Convergence within seconds

No bound at all; "eventually" is the whole promise

Two concurrent writes both survive

Only if you choose a merge rule; last-writer-wins silently drops one

In practice the gap is usually short. Copies in one data center typically catch up within milliseconds, and copies in another region within about a second. Usually short is not always short: under load or during a partition the window stretches, and the promise gives you no number to plan around. Why timestamps are a poor merge rule is Time, clocks & ordering.

5 · The practical middle

Session guarantees fix the bugs users actually notice

Most users never notice a stale copy. They notice when the system contradicts them. Four promises stop this. They are the session guarantees: promises about one client's own sequence of reads and writes rather than about the system as a whole.

Read-your-writes rules this out: after your own write, your own reads must reflect it. Everyone else may still see Elm Rd for a moment; the promise is scoped to you.

Guarantee

Promise

Bug it prevents

Answers in a partition?

Read-your-writes

Your reads reflect your earlier writes

You save a change; the page shows the old one

Yes, if you stick to one replica

Monotonic reads

Your reads never go back in time

An order appears, vanishes, then is back

Yes

Monotonic writes

Your writes apply everywhere in your order

Edit 2 lands before edit 1 on a copy, which keeps edit 1

Yes

Writes-follow-reads

A write is ordered after the reads it depended on

Your reply appears on a copy without the message it answers

Yes

All four are cheap. Pinning a session to one replica gives read-your-writes and monotonic reads at once; a version number carried by the client, which a replica waits to reach, covers the rest. Together they amount to causal consistency for one client, which is why they sit just below it on the ladder.

6 · Choosing

Pick a model per feature, not per system

Which model? Wrong question, if asked once per system. Ask it per feature. The shop's gift-card balance, stock counts, wishlist counter, your profile and the sign-up form live in the same two copies and need different answers.

Feature

Model

Why

Gift-card balance; the last unit in stock

Linearizable

Two cities each selling the last unit is money lost; the check needs the one true copy

Username uniqueness at sign-up

Linearizable

"Is it taken?" asked of a stale copy says no twice; a lagging copy cannot enforce an invariant

Your own profile edit

Read-your-writes + monotonic reads

You must see your change at once; others can wait a second

Wishlist count on a product

Eventual

Off by one for 200 ms harms nobody, and every page view reads it

Shopping cart

Causal, or eventual with a merge rule

Must stay writable through anything; two versions can be merged

The price rises with each rung up. A linearizable operation waits for a round trip between the cities, about 70 ms between London and New York, and must refuse to answer while they cannot talk. An eventual one answers from the local copy and keeps answering through the outage. How that trade is forced, and what it costs when nothing is broken, is CAP & PACELC.

Check yourself

4 questions

1. A read returns the new value. A later read, by another client, returns the old value. Which model is violated?
2. A user saves a new address and the next page load shows the old one. Which guarantee is missing?
3. A database offers serializable transactions. A transaction reads a row that another transaction committed a second earlier. Does the read see the committed value?
4. What is the strongest model a system can keep while still answering every client during a partition (if each client sticks to one replica)?

Takeaways

Remember this

  • "Consistency" means invariants in ACID, linearizability in CAP, and what copies may show in replication; consistent hashing is unrelated.
  • Linearizable: as if one copy, each operation at one instant between start and end. Serializable orders transactions and does not imply freshness.
  • Sequential drops real time, causal drops the shared order, eventual promises only that copies converge once writes stop.
  • Session guarantees (read-your-writes, monotonic reads, monotonic writes, writes-follow-reads) are cheap and stop the bugs users notice.
  • Choose per feature: balances and uniqueness need linearizability, counters can be eventual, and every rung up costs a round trip and availability.