Replication and consistency
Copies make a system available. They also make “what is the current value?” a real question.
You replicate data for three reasons, and it is worth naming which one you are buying: surviving a machine’s death (durability, availability), putting data near its readers (latency), and spreading read load. The price is one question that never goes away: when the copies momentarily disagree, what does a read return?
Leader–follower, and the shape of lag
The workhorse arrangement: writes go to one leader, which streams them to followers. The first design decision is when the leader acknowledges:
| Mode | Ack when | You gain | You risk |
|---|---|---|---|
| Asynchronous | leader has it | lowest latency | leader dies → acknowledged writes lost |
| Semi-synchronous | leader + one follower | no single-node loss | slightly slower; the usual compromise |
| Synchronous (all) | every follower | strongest durability | one slow node stalls all writes — rarely used as stated |
Because followers run behind, lag surfaces as concrete, nameable anomalies — learn them by the user story: you post a comment, refresh, and it is gone (read your own writes violated — your write hit the leader, your read a stale follower); you refresh twice and the comment flickers in and out (monotonic reads violated — second read hit a more stale replica); an answer appears before the question it replies to (consistent prefix violated). Each has a standard patch — pin a user’s reads to the leader briefly after their writes, pin a session to one replica, order causally related items through one partition — but you must know you are buying the patch.
Failover is the other sharp edge. Detecting a dead leader is Stage 1’s ambiguity all over again (slow ≠ dead); promoting a follower during async lag can silently discard the last acknowledged writes; and the old leader coming back convinced it still leads is split brain — two leaders accepting conflicting writes. Doing this safely is precisely the consensus problem, which is why Stage 4 exists.
The consistency ladder
A consistency model is the honest label on the jar — a contract about which read results are legal. The rungs you will actually discuss:
| Model | The promise | Feels like |
|---|---|---|
| Linearizable | as if one copy; every op atomic at some instant; reads see the latest write | a single machine — the gold standard, at a latency price |
| Sequential | one global order everyone agrees on, but not tied to real time | consistent, possibly stale together |
| Causal | whatever happened-before is seen in order; concurrent things may differ | conversations make sense; often the sweet spot |
| Session guarantees | read-your-writes, monotonic reads — per client | “I am not confused about myself” |
| Eventual | stop writing and replicas converge, eventually | anything goes, briefly |
The professional skill is naming the rung per piece of data: the account balance wants linearizable; the like counter is happily eventual; the comment thread wants causal. And read CAP narrowly, because it is narrow: during a partition, a system must choose between serving possibly-stale answers and refusing to answer. That is all it says. On a healthy network the operative trade is latency versus freshness — waiting for more replicas buys stronger answers at slower speeds.
Quorums — the dial
Leaderless stores (the Dynamo family) make the trade tunable per request: write to W of N replicas, read from R, and if R + W > N the read set must overlap the write set, so at least one consulted replica has the newest value (the client or coordinator reconciles versions — vector clocks from Stage 2 report which). With N = 3: W = 2, R = 2 balances both paths; W = 3, R = 1 makes reads cheap and writes fragile; W = 1, R = 1 is fast and guarantees nothing. Production wrinkles to know by name: sloppy quorums (during a partition, accept writes on stand-in nodes to stay available) and hinted handoff (those stand-ins deliver the writes home later) — availability preserved, overlap guarantee temporarily traded away.
One more tool for the concurrent-writes problem deserves a name: CRDTs — data types (counters, sets, registers) built so concurrent updates merge deterministically by construction, no coordination needed. Where your data fits one (likes, presence, shopping carts), conflict resolution stops being your code’s problem at all.
A map of every model and how they relate. Keep it open while you read anything else on this topic.
Why the CAP theorem is narrower than the way people cite it, and what to reason about instead.
Real databases tested to destruction. Read one for a system you use — it will change how you trust it.