DDIA Chapter 5: Replication
Part II: Distributed Data
Replication copies data for latency, availability, and read scale. The hard part is ongoing change, sync vs async, failover, lag, and conflicts.
Single-leader replication
Writes go to a leader; followers apply the change stream; clients may read any replica. Common and well understood. Fully synchronous replicas stall writes when a follower hangs, so production often syncs one (or a few) and leaves others async.
Failover elects a new leader, risks include unreplicated writes and split brain. Replication formats: statement-based (fragile), WAL (coupled to storage), logical logs (better decoupling), triggers (flexible, heavier).
Replication lag
Under async replication, readers can see the past. Application-level cures:
- Read-your-writes: read self-writes from the leader (or until a timestamp catches up)
- Monotonic reads: sticky replica so time does not go backwards for a user
- Consistent prefix: causally related writes stay ordered
If multi-minute lag is unacceptable, you need stronger guarantees than pure eventual consistency.
Multi-leader
A leader per datacenter improves locality and independence, but concurrent writes conflict. Avoid conflicts when possible; otherwise last-write-wins, replica priority, merge, or explicit conflict records. Topologies (circular/star/all-to-all) each have failure and causality pitfalls. Often considered dangerous for good reason.
Leaderless (Dynamo-style)
Clients write/read several replicas; quorums w + r > n detect freshness. Repair via read repair and anti-entropy. Concurrent writes need merge / version vectors; last-write-wins converges by discarding data.
flowchart TD
Clients --> Leader
Leader --> F1[Follower]
Leader --> F2[Follower]
Clients --> F1
Clients --> F2
In code
Snippets below use Java, SQL, or plain text as labeled.
Quorum intuition:
n = 3
w = 2, r = 2 => w + r > n (overlap sees a fresh write)
w = 1, r = 1 => faster, staler
Read-your-writes routing:
public Profile readProfile(UserId id, Optional<Instant> lastWrite) {
if (lastWrite.isPresent()
&& clock.instant().isBefore(lastWrite.get().plusSeconds(5))) {
return leader.read(id);
}
return replica.read(id);
}
Statement-based pitfall:
UPDATE accounts SET last_active = NOW() WHERE id = 42;
-- Prefer replicating the concrete value the leader used
UPDATE accounts SET last_active = '2026-09-30T12:00:00Z' WHERE id = 42;
What stuck
Async replication is common, so be explicit about lag. Failover can lose unreplicated writes or split the leadership. Quorums and version vectors are the Dynamo toolkit.