# DDIA Ch. 6 — Replication: a reading companion

**19,866 words, 4 top-level sections, 7 exercises.** Three architectures, and
the chapter's real work is teaching you what each one gives up.

*The book's words appear in exactly two forms: blockquotes, and short spans in
quotation marks mid-sentence. Both are machine-checked verbatim against
the source epub by `tools/verify_quotes.py`. Everything else — read-weights,
misreads, cross-chapter threads — is my editorial judgment, and `[bracketed]`
words inside a quote are mine too. Trust the quotes; argue with the rest.*

## Before you start

This chapter assumes less than the ones around it, which is why it reads easily
and misleads badly. **Ch. 1** — the reasons to distribute at all (latency,
availability, read throughput); the chapter opens by naming them and never
re-argues them. **Ch. 4** — the write-ahead log, because "Write-ahead log
shipping" is one of the three replication-log formats and assumes you know what
a WAL already is. Nothing else is load-bearing. Note the scope line the chapter
sets in its second paragraph and quietly relies on throughout: <q class="book">we
will assume that your dataset is small enough that each machine can hold a copy
of the entire dataset</q>. Every "just add a replica" argument here dies in Ch. 7.

## The chapter in one claim

> If the data that you're replicating does not change over time, replication is
> easy; you just need to copy the data to every node once, and you're done. All
> the difficulty in replication lies in handling changes to replicated data,
> and that's what this chapter is about.

Read the three architectures as three answers to *where do changes get ordered*.
Single-leader orders them at one node; multi-leader orders them nowhere and pays
in conflicts; leaderless orders them nowhere and pays in quorums and version
vectors. Every trade-off in the chapter is downstream of that one question.

## Section map

| Section | Words | Read | What it's for | Then run |
| --- | ---: | --- | --- | --- |
| **Single-Leader Replication** | 6,745 | | The default everywhere. Read it as the baseline the other two are deviations from. | |
| &nbsp;&nbsp;Synchronous Versus Asynchronous Replication | 641 | **Close** | Short and the highest-value 641 words in the chapter. The semisynchronous compromise is what your database actually does. | — |
| &nbsp;&nbsp;Setting Up New Followers | 883 | Ref | Snapshot + log position + catch up. The "Databases Backed by Object Storage" box is a good 2025 aside, unrelated to the chapter's argument. | — |
| &nbsp;&nbsp;Handling Node Outages | 1,290 | Skim → **Close** | Skim "Follower failure"; read "Leader failure: Failover" closely — the GitHub incident and split brain are the chapter's sharpest war stories. | — |
| &nbsp;&nbsp;Implementation of Replication Logs | 999 | **Close** | Three log formats, three different operational consequences. The one that decides whether you can upgrade without downtime. | [statement-based-replication](statement-based-replication.md) |
| &nbsp;&nbsp;Problems with Replication Lag | 2,128 | **Close** | The core of the chapter and the source of every anomaly you'll meet in production. Three named guarantees, three exercises. | [read-your-writes](read-your-writes.md), [monotonic-reads](monotonic-reads.md) |
| &nbsp;&nbsp;Solutions for Replication Lag | 338 | **Close** | Tiny. Its actual advice is "use a database that doesn't have this problem." | — |
| **Multi-Leader Replication** | 5,370 | | | |
| &nbsp;&nbsp;Geographically Distributed Operation | 1,309 | **Close** | The four-way comparison (performance, regional outages, network problems, consistency) is the decision table. | — |
| &nbsp;&nbsp;Sync Engines and Local-First Software | 1,138 | Skim | New in 2e and genuinely interesting — Figma, Linear, Automerge — but it's an application of the model, not part of it. Skip if you're here for databases. | — |
| &nbsp;&nbsp;Dealing with Conflicting Writes | 2,649 | **Close** | The densest subsection in the chapter. LWW, siblings, CRDTs and OT, and the Amazon cart anomaly. | [lww-clock-skew](lww-clock-skew.md), [g-counter-crdt](g-counter-crdt.md) |
| **Leaderless Replication** | 5,425 | | | |
| &nbsp;&nbsp;Writing to the Database When a Node Is Down | 2,164 | **Close** | Quorums, read repair, hinted handoff — and then the list of cases where `w + r > n` isn't enough. | [quorum-limits](quorum-limits.md) |
| &nbsp;&nbsp;Single-Leader Versus Leaderless Replication Performance | 721 | **Close** | New in 2e, and the best argument in the chapter for leaderless: no failover means gray failures cost you nothing. | — |
| &nbsp;&nbsp;Multi-Region Operation | 233 | Ref | Cassandra/Riak specifics. | — |
| &nbsp;&nbsp;Detecting Concurrent Writes | 2,032 | **Close** | The payoff. Happens-before, siblings, version vectors — and the definition of "concurrent" that the rest of the book uses. | [version-vectors](version-vectors.md) |
| **Summary** | 2,326 | Ref | The three-guarantee recap (read-after-write, monotonic reads, consistent prefix) is worth re-reading; the rest restates. | — |

## Load-bearing claims

**1. Asynchronous replication makes "committed" conditional.** The single most
consequential sentence about the configuration almost everyone runs, buried in
the failover subsection:

> The most common solution is for the old leader's unreplicated writes to simply
> be discarded, which means that writes you believed to be committed weren't
> durable after all.

**2. LWW does not mean "last."** The chapter defines the term and then
immediately says the term is wrong — and this is the claim
[lww-clock-skew](lww-clock-skew.md) makes physical:

> the real meaning of LWW is this: when the same record is concurrently written
> on different leaders, one of those writes is randomly chosen to be the winner
> and the other writes are silently discarded, even though they were
> successfully processed by their respective leaders

"Randomly" is doing real work there. It is not "the newer one wins"; it is "an
arbitrary one wins, and you are not told."

**3. `w + r > n` is a probability, not a guarantee.** The condition is derived
cleanly, illustrated, and then walked back over five bullet points —
[quorum-limits](quorum-limits.md) is the exercise for exactly this gap:

> although quorums appear to guarantee that a read returns the latest written
> value, in practice it is not so simple

The chapter's own summary of what `w` and `r` actually buy you: <q class="book">it's
wise to not take them as absolute guarantees</q>.

**4. "Concurrent" is defined by knowledge, not by clocks.** The definition the
rest of the book (Ch. 9, Ch. 10, Ch. 13) is built on, and the one
[version-vectors](version-vectors.md) implements:

> we can simply say that two operations are concurrent if neither happens before
> the other

The sidebar makes the consequence explicit: two writes made hours apart are
concurrent if neither knew about the other. Time doesn't enter into it.

**5. Multi-leader forfeits constraints, permanently.** Not a limitation of any
particular product — the reason single-leader survives:

> you can't guarantee that a bank account won't go negative or that a username is
> unique; it's always possible for different leaders to process writes that are
> individually fine (paying out some of the money in an account, registering a
> particular username) but that violate the constraint when taken together with
> another write on another leader

If your invariant spans writes, you need a single point of ordering. Ch. 13's
[uniqueness-needs-total-order](../ch13/uniqueness-needs-total-order.md) is this
sentence turned into a running system.

## Common misreads

**"Eventual consistency means a second or two."** It means no bound at all. The
word is vague on purpose, and the chapter says so:

> The term "eventually" is deliberately vague; in general, there is no limit to
> how far a replica can fall behind.

*If you read one thing closely in this chapter, make it "Problems with
Replication Lag."* Every "it'll have caught up by then" assumption dies here.

**"Synchronous replication means my followers are all up to date."** No database
does that, because none could survive it:

> it is impracticable for all followers to be synchronous; any one node outage
> would cause the whole system to grind to a halt

What you actually get is *semisynchronous* — one synchronous follower, the rest
async — so "synchronously replicated" means two copies, not all of them.

**"Read-your-writes and monotonic reads are the same guarantee."** They fail for
different people. Read-after-write is about *your own* writes and says nothing
about anyone else's; monotonic reads is about *ordering across your own reads*:

> monotonic reads mean only that if one user makes several reads in sequence,
> they will not see time go backward

Run [read-your-writes](read-your-writes.md) and
[monotonic-reads](monotonic-reads.md) back to back — same lag, same cluster, two
distinct failures, two distinct fixes (route to the leader vs. pin to one
replica).

**"Statement-based replication is just shipping SQL, so it's fine."** It is the
one replication format that can silently diverge two replicas that both applied
every write:

> Any statement that calls a nondeterministic function, such as NOW to get the
> current date and time or RAND to get a random number, is likely to generate a
> different value on each replica.

[statement-based-replication](statement-based-replication.md) produces the
divergence in two rows.

**"CRDTs solve conflict resolution."** They automate *merging*; they cannot
invent an answer that doesn't exist:

> There are limits to what is possible with conflict resolution. For example, if
> you want to enforce that a list contains no more than five items, and multiple
> users concurrently add items to the list so that there are more than five in
> total, your only option is to drop some of the items.

Which is claim 5 again, from the other side. [g-counter-crdt](g-counter-crdt.md)
shows what convergence *does* buy — 80 increments preserved that LWW throws away.

**"A version vector is a vector clock."** Two different structures with an
unhelpfully similar name; the book flags it in a note rather than a section, so
it is easy to miss:

> when comparing the state of replicas, version vectors are the right data
> structure to use

## Connects to

**Back:** Ch. 1 — the availability/latency/throughput case for replicating at
all, assumed rather than restated. Ch. 4 — the write-ahead log that "WAL
shipping" ships, and the reason that format couples replication to the storage
engine version.

**Forward:** Ch. 7 is the direct sequel — this chapter's stated assumption is
that the whole dataset fits on one machine, and sharding removes it. Ch. 8
supplies what "Solutions for Replication Lag" recommends and doesn't explain
(transactions), and its write-skew story is the single-node version of claim 5.
Ch. 9 explains why LWW's timestamps can't be trusted — clock skew is assumed
here, formalized there. Ch. 10 supplies both things this chapter defers: the
consensus that makes leader election safe, and linearizability, the guarantee
"read from the leader" is reaching for. Ch. 12 picks up the logical log as
change data capture. Ch. 13 returns to conflict detection at scale.
