Part 3 · 2 chapters · ~20 min

Replication

Single-leader, multi-leader and leaderless replication: who accepts writes, synchronous versus asynchronous followers, failover and fencing, quorums; then replication lag as user-visible anomalies with their fixes, and conflict resolution by last-write-wins, siblings and CRDTs.

7

Leader-follower, multi-leader, leaderless

who accepts writes
  1. Single-leader: conflict-free ordering, with one machine's worth of write throughput.
  2. Synchronous or asynchronous followers. Semi-synchronous (one sync standby) is the usual compromise.
  3. Failover: promote a follower and fence the old leader with an epoch.
  4. Multi-leader: local writes everywhere, at the price of conflicts.
  5. Leaderless: W + R > N quorums, with read repair.
  6. Choose single-leader unless you have a reason you can name.
code
-- Postgres: how far behind is each replica? (run on the primary)
SELECT application_name, state, sync_state,
       pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS bytes_behind,
       replay_lag
FROM pg_stat_replication;

--  application_name | state     | sync_state | bytes_behind | replay_lag
--  standby-az-b     | streaming | sync       |            0 | 00:00:00.0012
--  replica-reports  | streaming | async      |     48213992 | 00:00:07.4   ← reports are 7 s stale
THREE SHAPES OF REPLICATION
single-leader, multi-leader and leaderless: who accepts writes, how they spread, and what can conflict
swipe the figure sideways, or tap expand for full screen
1/6
single-leader
Single-leader (Postgres, MySQL, MongoDB, most managed databases): all writes go to the leader, which streams its change log to followers; followers serve reads. Simple and conflict-free: the leader's order is the order. Its limits: write throughput is one machine's, and a leader far from a user adds latency to every write.
8

Lag, anomalies and conflicts

what users see, and how conflicts resolve
  1. Read-your-writes: read your own data from the leader, or wait until the replica reaches your write position.
  2. Monotonic reads: pin each user to one replica, or track the highest position seen.
  3. Consistent prefix: co-locate causally related writes.
  4. Last-write-wins silently loses data.
  5. Siblings keep both versions and merge on read.
  6. CRDTs build the merge into the data type itself.
code
// read-your-writes with a position token (Postgres LSN) carried in the session
// after a write on the primary:
const { lsn } = await primary.one('SELECT pg_current_wal_lsn() AS lsn');
session.minLsn = lsn;

// on the next read, use a replica only if it has replayed past the user's write
async function readProfile(userId: string, session: Session) {
  const r = pickReplica();
  const ok = await r.one('SELECT pg_last_wal_replay_lsn() >= $1 AS ok', [session.minLsn]);
  return (ok.ok ? r : primary).one('SELECT * FROM profiles WHERE user_id = $1', [userId]);
}
the frontend version
Optimistic UI (the React course part 8) is a local read-your-writes guarantee: the client shows its own write immediately, whatever the replicas say. Reconcile it against the server response, not against the next read, which may come from a lagging replica.
REPLICATION LAG AND CONFLICTS
the anomalies users see when reads hit a lagging replica, and the ways conflicting writes are resolved
swipe the figure sideways, or tap expand for full screen
1/6
read your writes
Read-your-writes: a user updates their phone number (written to the leader) and the next page load reads from a lagging follower, showing the old number: the user thinks the save failed. Fix: read a user's own data from the leader for a while after they write it, or read from a replica only once it has caught up to the user's last write position (a log sequence number carried in the session).