Consistency & Isolation Models
When many users, many objects and many copies exist at once, which histories does the system promise never to show, and who writes the code for the histories it does show?
Who this mechanism is for: a developer who writes backend code and knows basic SQL, but has never studied what "isolation level", "strong consistency" or "eventual consistency" really promise. You do not need to know how a database is built inside. Every technical term is explained the first time it appears, and again in the glossary at the end. This mechanism explains ideas, not products: when it mentions PostgreSQL, MySQL, Oracle or Cassandra, it is to show that the same idea has different names in different places.
The story we will follow
Anika is a backend engineer at Pebble, a small company with a mobile wallet app. Users hold balances, send money to friends, pay merchants, join promotions and attach short notes to payments. Anika owns the ledger service, the code that records every movement of money. Her colleague Tomás is the platform engineer. He owns the database servers, the read copies (replicas), the caches and, later, a second region.
Pebble's ledger is a PostgreSQL-style database in Frankfurt: one primary (the copy that accepts writes) and read replicas. Peak load is about 40,000 transfers per minute. Copies normally lag the primary by about 20 ms, and by up to 2 s under load. Later Pebble opens a second region in Singapore, 80 ms of network delay away. All numbers in the story are illustrations.
Over the six parts of this mechanism Anika meets six problems, one at the start of each article. Each problem looks like a bug in the code. None of them is. Each is a consequence of what a consistency or isolation level does not promise. At the end of each article we go back to Anika and solve her problem with the part's ideas.
The main idea of this whole mechanism:
How this mechanism is organized
- 1
A promise about histories
What kind of thing is a consistency model, why are there two separate families of them, and which three pieces of arithmetic govern them?
CaseOne read replica, and payments that seem to vanish
- 2
Transactional isolation
When many transactions touch many rows, which interleavings may a reader see, and why are the standard level names so confusing?
CaseA vanishing bonus and a negative joint balance
- 3
Distributed consistency
When one object has many copies, what is the price of recency, and what are linearizability, sequential and causal consistency?
CaseFast reads in Singapore, and a balance a second old
- 4
Sessions, convergence and quorums
How do session guarantees, eventual consistency, CRDTs and quorum settings really behave?
CaseThe old name comes back after a refresh
- 5
The unification and its price
When do you truly need coordination? CAP, PACELC, highly available transactions, invariant confluence, CALM, external consistency, and what can be verified.
Case1,140 bonuses from a promotion of 1,000
- 6
What consistency forbids
What does this whole mechanism forbid, what does each escape cost, and what is the decision procedure?
CaseA design review: which guarantee does each screen need?
After that: a summary, hands-on labs, interview questions and a glossary.
A request: do not skip the small examples with two or three transactions. Almost every claim here can be checked by writing three short transactions in a database console. The labs do exactly that.
What do I do, and what does each option cost?
Choose an isolation level
Transactions on one database read and write the same rows: rewrite the operation, push the rule into a constraint, or pick read committed, snapshot isolation or serializable? Four questions, cheapest answer first.
ChooseDecide on consistency
Data is replicated across machines or regions: does your rule need coordination at all, can you split the budget so replicas act alone, or do you need real-time ordering? Five questions, cheapest answer first.
Choose
Can I see it myself?
Anomaly count equals rate times window
Count conflicting operations inside a window and compare with λ × W, from one SQL statement to replica lag under load.
SimulatePython with NumPyMeasure the Dekker pattern and the price of `r + w ≥ d`
Two regions with an 80 ms delay run the Dekker test: local reads and writes can both read 0; only waiting for the other copy removes it.
Simulate · Break itPythonCount the shapes with a tiny dependency-graph checker
Build ww, wr and rw edges from small histories and classify lost update, write skew and read skew by their cycles.
SimulatePythonReproduce the lost update at Read Committed, then fix it three ways
Lose an update under Read Committed in PostgreSQL, then fix it four ways.
Real system · Break itDocker, PythonSame name, different promise: compare engines
One phantom test at the level PostgreSQL and MySQL both call Repeatable Read, with different results.
Real system · Break itDocker, PythonWrite skew under Repeatable Read, and the two cures
Two transactions each check a total, then withdraw from different accounts: write skew under Repeatable Read, and the two cures.
Real system · Break itDocker, PythonRead-your-writes with a replica, and a lost token
Write on a PostgreSQL primary, read from a lagging replica, then carry a log-position token, then lose it.
Real system · Break itDocker, PythonAnomaly rate equals window times rate
Stale reads from a lagging replica against λ × W, for three lags, then reads routed to the primary after a write.
Real systemDocker, PythonLWW versus a G-counter under clock skew
Three replicas, one clock 3 s ahead, 1,000 increments: last-writer-wins and max lose them; a G-counter keeps all.
SimulatePythonR + W > N is not recency
A toy N = 3 register: a failed W = 2 write leaves reads with R = 2 going back and forth.
SimulatePythonCount I-confluence in your own schema
Classify every constraint of a schema as invariant-confluent or not, and price the escrow for its bounds.
SimulatePythonRun an Elle-style check on your own database
A list-append workload against PostgreSQL at three isolation levels, with the dependency graph rebuilt and searched for cycles.
Real system · Break itDocker, Python
Can I reason about it under questioning?
Interview questions
Short questions on consistency, such as isolation levels and their anomalies, linearizability, causal consistency, session guarantees, CRDTs, quorums, CAP and coordination, each with an answer you could give aloud and a link to the full explanation.
Scenarios
Longer problems on consistency, of the kind asked in senior interviews: each one estimated with numbers, diagnosed, and answered with its trade-offs.
The tensions this mechanism takes a position on. Each recurs across mechanisms.
Ideas this mechanism meets that keep coming back, mechanism after mechanism.
Costs are conserved
Costs are conserved, never removed.
The algebra decides
What can be skipped, pushed down, parallelized, merged or precomputed is determined by the algebra of the function, not the layout of the data.
Sound approximations
When exactness is too expensive, use a sound approximation.
Granularity mismatch
Granularity mismatch creates amplification.
Little's Law
Concurrency = Throughput × Latency.
Show all 12 principlesShow fewer
Independence is assumed
Independence is assumed everywhere and is true almost nowhere.
Immutable storage grows indirection
An immutable substrate grows an indirection layer plus a collector.
Absence is not evidence
Absence of an event is not absence of a failure.
Masking moves failure
Masking a failure moves it from a channel with a schema to a channel without one.
The end-to-end argument
Guarantees compose to the weakest link, and only endpoint guarantees are real.
Randomization replaces coordination
Randomization can replace coordination.
Coordination cannot be made cheaper
Coordination is the only thing you cannot make cheaper.