Skip to the chapter
←System DesignGGroundworkSDSystem Design
System Design/Intermediate/I5
12 / 36 written chapters
/

The cover
  1. B1The mental model
  2. B2Client-server basics
  3. B3Vertical vs horizontal
  4. B4Databases in design
  5. B5Caching fundamentals
  6. B6APIs & communication
  7. B7Walkthrough: URL shortener
  1. I1Load balancing in depth
  2. I2CDNs
  3. I3Message queues & async
  4. I4Consistency models
  5. I5Replication
  6. I6Rate limiting & throttling
  7. I7Designing for availability
  8. I8Storage systems
  9. I9Search systems
  10. I10Microservices
  11. I11Security basics
  12. I12Walkthrough: feed/chat
  13. I13Walkthrough: notifications
  1. A1CAP theorem in depth
  2. A2Transactions and isolation
  3. A3Storage engines
  4. A4Sharding at scale
  5. A5Time, ordering and IDs
  6. A6Distributed consensus
  7. A7Batch & stream processing
  8. A8Fault tolerance
  9. A9Observability at scale
  10. A10Release safety
  11. A11Capacity estimation
  12. A12Case studies
  13. A13Walkthrough: key-value store
  14. A14Walkthrough: web crawler
  15. A15Walkthrough: payments
  16. A16Tradeoff thinking

SDI5 · Part 2 · Intermediate

Replication

Keeping copies of the same data on several machines is easy until the machines disagree, and then every design choice is a decision about which copy you are willing to lose.

26 min read3 diagrams10 sections0 exercises
12 of 36

In this chapter

  • Why copy data at all, and why a copy is not a backup
  • Single leader: one place decides the order
  • Synchronous or asynchronous: you are choosing what a crash may cost
  • Failover: promoting a follower is easy, doing it safely is the problem
  • Followers, lag and the operational cost of read replicas

and 5 more

about 26 min
10On this page
  1. Why copy data at all, and why a copy is not a backup
  2. Single leader: one place decides the order
  3. Synchronous or asynchronous: you are choosing what a crash may cost
  4. Failover: promoting a follower is easy, doing it safely is the problem
  5. Followers, lag and the operational cost of read replicas
  6. Multi-leader: writes in more than one place, and the bill that arrives
  7. Leaderless: any replica takes writes, and repair does the cleaning
  8. How the four systems you will be asked about really do it
  9. Choosing, in one table
  10. Recognizing it in an unseen problem

Why copy data at all, and why a copy is not a backup

Replication means keeping the same data on more than one machine, and it does three separate jobs that are easy to blur together. It gives availability: when one machine dies another already holds the data. It gives read capacity: copies can serve queries so the original does not have to. And it gives locality: a copy in Frankfurt answers a European user in a few milliseconds instead of a 70 to 90 ms round trip to US East. Each job wants a different trade-off, which is why "we'll add a replica" is the start of a design conversation and not the end of one.

A replica is not a backup. Replication copies mistakes as faithfully as it copies data: a bad DELETE or a bug that corrupts rows reaches every follower within moments. Backups and point-in-time recovery protect against your own mistakes; replicas protect against hardware. This chapter takes the three families in order: one leader with followers, several leaders, and no leader at all. It spends its time on the places each one loses data, because that is what interviewers and incidents probe. How stale a follower's reads can be is covered in the consistency models chapter, and the quorum arithmetic behind leaderless stores is covered there too; both are linked here, not repeated.

Single leader: one place decides the order

In the most common arrangement one node, the leader (also called primary or source), accepts every write. It appends the change to a log and ships that log to followers (replicas, standbys), which apply the entries in the same order. Because there is one writer and one order, followers can never disagree about what happened, only about how far along they are. That single property is why this design dominates relational databases.

client leader log: ..., 41, 42 follower 1 (sync) commit waits for this ack follower 2 (async) applies when it gets there follower 3 (async) may be seconds behind 1 write 2 ship the log Only the sync follower is certain to hold entry 42 at "committed".
The log, not the data files, is what travels. Whether the client waits for a follower is the entire sync-versus-async decision.

What exactly is in the log

Log styleShipsWhere you meet itCatch
Physical (write-ahead log)Low-level changes to disk pagesPostgreSQL streaming replication sends WAL records as they are generated, without waiting for a 16 MB segment to fillThe standby is a copy of the whole cluster, so it replays everything the primary does
Row-based (logical)Which rows changed and their new valuesThe MySQL binary log; row-based logging is the default in MySQL 8.4. PostgreSQL logical replication also streams row changesLarger logs for bulk updates, but the follower never has to guess
Statement-basedThe SQL text itselfMySQL still supports it (its manual says changing binlog_format is deprecated), and its mixed mode uses it by defaultThe follower re-executes the statement, so anything non-deterministic (a random number, the current time) can produce a different row on each machine

The log style decides what else replication can do. A physical standby is the simplest and fastest way to get a failover copy. A logical stream can feed a different database, a search index or a cache invalidator, which is why change-data-capture tools read the logical log.

Synchronous or asynchronous: you are choosing what a crash may cost

The leader can tell the client "committed" at three moments: after its own disk flush, after a follower has the entry, or after a follower has applied it. The earlier it answers, the faster the write and the larger the window in which a leader crash destroys an acknowledged write. PostgreSQL exposes the whole range through synchronous_commit, and its manual states the baseline plainly: with asynchronous streaming, transactions that committed on the primary may not have reached the standby when it crashes, causing data loss.

SettingCommit returns afterAcknowledged write can be lost if…
Asynchronous (synchronous_standby_names empty, the default)The leader's own WAL flushThe leader dies before the standby received the record
remote_writeThe standby has received the record and handed it to its operating system, not necessarily flushed itThe primary is lost and the standby's operating system crashes before it flushes the record (the manual: the write survives a crash of the standby's PostgreSQL, not of its operating system)
on with a standby namedThe standby has flushed the commit record to durable storageBoth machines lose their storage (the manual: the primary and every synchronous standby suffer corruption of their database storage)
remote_applyThe standby has replayed the record, so it is visible to queries thereSame as on, and a read from a synchronous standby that acknowledged sees the write

Notice the last row. With plain on, the standby has the record on disk but may not yet have replayed it, so a read served from that "synchronous" standby can still be stale. Synchronous replication buys durability; only remote_apply also buys read-your-writes from the follower, at the cost of waiting for replay too. MySQL's version is semi-synchronous replication: the source waits until at least one replica has received the events and written them to its relay log on disk, and by default it waits after the binary log is synced but before the transaction commits in the storage engine. If no replica answers within the timeout, the source quietly reverts to asynchronous replication and returns to semi-synchronous when a replica catches up. Read that twice: your durability promise silently weakens in exactly the moment a replica is unhealthy.

The price of waiting

Waiting for a follower adds at least one network round trip to every commit. Using the planning round trips from the capacity chapter: a follower in the same availability zone adds about 0.5 ms, one in another zone 1 to 2 ms, and one across the US or to Western Europe 60 to 90 ms. A single connection that commits one transaction after another can then do at most 1 ÷ 0.08 = 12.5 commits a second against a distant synchronous standby, where the same connection could do hundreds locally. Concurrency and group commit recover throughput across many connections, but each user-visible write still pays the latency. That is why synchronous replication across regions is rare and synchronous replication across zones is common.

The second price is availability. If the single synchronous standby is down and the primary insists on its acknowledgement, writes stop. PostgreSQL's manual warns that such commits may never complete if a synchronous standby crashes. The standard fix is a quorum: ANY 1 (s1, s2) commits when either standby answers, while FIRST 1 (s1, s2) keeps a priority order and promotes the next standby into the synchronous role when the current one disconnects.

Write path needsEach machine 99.9% available, independentWrites available
Primary only (async)0.99999.9%
Primary and one specific synchronous standby0.999 × 0.99999.8%
Primary and any 1 of 2 standbys0.999 × (1 − 0.001 × 0.001) = 0.999 × 0.99999999.9%

The independence assumption is generous, since standbys in one zone share fate, but the shape is right: one mandatory synchronous follower costs availability, and a quorum of followers gives the durability back without the cost.

Failover: promoting a follower is easy, doing it safely is the problem

When the leader fails, a follower must take over: something detects the failure, picks the follower that is furthest along, promotes it, and points clients and the remaining followers at it. PostgreSQL exposes promotion (pg_ctl promote or pg_promote()) and leaves the decision about when to external tooling or a managed service. In MySQL Group Replication a single-primary group elects a new primary automatically, preferring members on the lowest server version, then by member weight (default 50), then by lowest server UUID, and clients still have to be re-routed, by your proxy or by MySQL Router in an InnoDB Cluster.

old primary writes replicated acked, not yet shipped still taking writes: split brain standby applying the log, lag 40 ms promoted: new writes partition promotion At 5,000 writes a second, 40 ms of lag is 200 acknowledged writes lost. Fencing makes the old primary stop; reconciliation decides what to do with its extra 200.
Two separate problems share one diagram: the writes in the red box are lost by an async failover, and the red bar on the right is what happens if nobody stops the old primary.

Hazard 1: lost writes

With asynchronous replication the new primary is missing whatever the old one had acknowledged but not shipped. The size of that loss is lag times write rate: 0.040 s × 5,000 writes a second (the planning write rate for one relational primary) is 200 writes. Choosing the most advanced follower (highest log position) minimises the loss; a synchronous or quorum standby drives it to zero for the acknowledged writes it covers, provided the failover tool can compare the standbys' log positions and promote one that holds every acknowledged write. With a quorum of 1 out of 2, a promoted standby that happens to be the lagging one would silently drop acknowledged writes. The lost writes are not gone from the world: they sit on the old primary's disk, and someone has to decide whether to replay, discard or hand them back to users.

Hazard 2: two primaries

A false failure is worse than a real one. A network partition, a long garbage-collection pause or an overloaded primary that misses its heartbeat looks identical to a crash from outside. The failover tool promotes the standby, the old primary is still alive and still has clients connected, and now both accept writes. The distributed consensus chapter explains why quorum elections do not stop a stale leader from acting on resources outside the quorum, and why a fencing token is the cure. For databases the practical forms are:

  • Shoot the old primary (power it off, cut its network port, revoke its storage lease) before the promotion completes.
  • Make the old primary demote itself when it loses its lease, so it stops by its own clock.
  • Never let it rejoin as a primary. After promotion the cluster has moved to a new timeline, and the old primary holds writes that exist nowhere else. It must be rebuilt as a follower of the new primary, or its extra writes must be reconciled by hand. PostgreSQL standbys follow the switch automatically when recovery_target_timeline is latest, its default.

Detection is a trade-off too. A short timeout means a load spike triggers a needless failover (which itself causes load); a long one extends the outage. Tuning it down to a few seconds without fencing is how teams manufacture split brain.

⚠ A real 43-second partition became a 24-hour incident On 21 October 2018 maintenance on a failing optical link cut GitHub's US East Coast network hub off from its primary data center for 43 seconds. Its Orchestrator failover tooling, running a Raft quorum, promoted primaries in the West Coast data center during the gap. When the link returned, each side held writes the other did not: the post-incident analysis describes a few seconds of unreplicated writes, with 954 writes on one of the busiest clusters. Because both sides had unique data, GitHub could not simply fail back, and service was degraded for 24 hours and 11 minutes while it reconciled the data. GitHub's analysis points to several causes: the few seconds of unreplicated writes, nearly 40 minutes of new writes on the West Coast that blocked a simple fail-back, and a cross-country topology the application tier could not run well.

Hazard 3: things outside the database remember the old primary

If the old primary handed out identifiers 1001 to 1200 and those were emailed, cached or published before it died, the new primary's counter may start at 1001 again and reuse them. Clients with cached connections keep writing to the old address, and caches that were warmed from the old primary hold values the new primary never saw. Plan the redirect (DNS, a proxy, a service-discovery update) and the cache flush as part of failover, not after it. A planned switchover removes the first two hazards and shrinks the third: stop writes, let the follower catch up to the leader's position, demote the old leader, promote the follower, and nothing is lost. You still re-point clients and flush caches.

Followers, lag and the operational cost of read replicas

Lag, and the session guarantees that hide it, belong to the consistency models chapter. What belongs here is measuring it and knowing what makes it grow. PostgreSQL reports three separate lags per standby in its pg_stat_replication view: write_lag, flush_lag and replay_lag, each the time until the standby has written, flushed or applied recent WAL. They answer different questions: flush lag tells you about durability, replay lag tells you about what a reader sees. Alert on replay lag for read replicas.

Two hot-standby traps recur. A read-only query on a standby can conflict with the stream of changes it is replaying, for example when the primary vacuums away rows the query still needs, so replay is held up or the query is cancelled. Setting hot_standby_feedback tells the primary what the standby still needs and prevents the cancellations, at the cost of letting dead rows pile up on the primary. And a standby that disconnects with a replication slot makes the primary keep WAL for it, which the manual warns can fill the disk allocated for pg_wal. The max_slot_wal_keep_size setting caps how much WAL a slot may hold.

Multi-leader: writes in more than one place, and the bill that arrives

With several leaders, each accepts writes and forwards them to the others. It earns its keep in three situations: users in several regions who need local write latency (a US East to Europe write that waits on a 70 to 90 ms round trip feels slow), clients that must work offline (every phone is a leader that syncs later), and collaborative editing. The price is that two leaders can accept conflicting writes to the same record at the same time, and nothing in the architecture says which one is right.

The cheapest defence is to avoid the conflict: route every record to a home leader (a user's profile is written only in that user's home region) so that concurrent writes to one record cannot happen. That is single-leader per record with multi-leader plumbing, and it breaks only when the home region is down. When you cannot avoid conflicts you must pick a resolution rule. The rules, from cheapest to most careful:

RuleHow it worksWhat it loses
Last write wins (LWW)Each write carries a timestamp; the highest timestamp replaces the otherThe losing write, silently, with no error to its author. And "last" is decided by clocks that disagree
Keep both, resolve on readStore the concurrent versions as siblings and let the application merge them. Dynamo's shopping cart merges the divergent cartsNothing is lost, but deleted items can resurface, as the Dynamo paper says of the cart
Merge by construction (CRDT)Use a data type whose merge operation is commutative, associative and idempotent, so replicas that have seen the same updates reach the same stateYou are limited to types that have a merge: counters, sets, registers, sequences. Metadata can grow
Reject or serialiseDetect the conflict and abort one side, or send writes through one leaderAvailability: the aborted write has to be retried by someone

Dry run: the same two concurrent writes under LWW and under a CRDT

Two regions, A and B, both hold a profile with bio = "Hi" and a like counter of 5. Region A's clock is exact. Region B's clock runs 80 ms slow. Two users act at nearly the same time, and each region first applies the write locally.

Step (true time)Region ARegion BNote
0.000 sbio "Hi", likes 5bio "Hi", likes 5Replicas agree
10.000 swrites bio "Hello" stamped 10.000; likes 6 stamped 10.000unchangedA's clock is exact
10.020 sunchangedwrites bio "Hey" stamped 10.020 − 0.080 = 9.940; likes 6 stamped 9.940B's write is 20 ms later but looks 60 ms earlier. A's write cannot have reached B yet (the one-way delay is 35 to 45 ms), so the writes are concurrent
about 10.060 s, replication crossesreceives "Hey" @ 9.940; 9.940 < 10.000, so it keeps "Hello"receives "Hello" @ 10.000; 10.000 > 9.940, so it replaces "Hey"Both converge on "Hello"
Result under LWWbio "Hello"; likes 6bio "Hello"; likes 6Replicas agree, but the later bio edit is gone, and two +1 clicks became one
Result with a counter CRDT (5 is the starting value; a grow-only counter keeps one increment slot per replica, here A:1 and B:1, and merge takes the maximum of each slot){A:1, B:1}, 5 + 2 = 7{A:1, B:1}, 5 + 2 = 7No increment lost. The bio, being a plain overwrite, still needs a rule

Two lessons sit in that table. LWW converges, which makes it look safe, but convergence is not the same as keeping what users did. And the counter is exactly the case where you should not use overwrite semantics at all: model it as increments and the problem disappears. (A button that can also be undone needs separate increment and decrement slots, a PN-counter.)

How real systems handle multi-leader writes

  • DynamoDB global tables. In the default multi-Region eventual consistency mode, each item change is replicated asynchronously to the other Regions, and when the same item is modified in several Regions at once the modification with the latest internal timestamp wins on a per-item basis. A strongly consistent read returns the latest version only if the item was last updated in that Region, and transactions are atomic only within the Region where they ran, so another Region can briefly see part of one. The alternative multi-Region strong consistency mode replicates synchronously to at least one other Region before the write returns, requires exactly three Regions (three replicas, or two plus a witness), and does not support transactions or TTL. A write that collides with one in flight elsewhere fails with ReplicatedWriteConflictException and can be retried.
  • PostgreSQL logical replication. The manual says a conflict that produces an error, for example a duplicate on a unique key, stops replication until a person fixes it, either by changing the data or by skipping the transaction, which it warns can leave the subscriber inconsistent. When a row was last changed by a different origin, the incoming update is applied anyway, so the remote write always wins (the conflict is logged only if track_commit_timestamp is on at the subscriber). There is no general resolution policy. Treat it as a way to move changes between databases that do not write the same rows.
  • MySQL Group Replication. Multi-primary mode is optimistic: members execute transactions locally and roll them back if the group cannot certify them. A transaction run under SERIALIZABLE isolation fails to commit in a multi-primary group, and a group is limited to 9 members. Consensus on transaction order is Paxos-based.

Leaderless: any replica takes writes, and repair does the cleaning

Dynamo-style stores such as Cassandra have no leader. A client or coordinator sends each write to all N replicas of the key and counts acknowledgements against W; reads gather R. The arithmetic of R + W > N, the worked example, and the hinted-handoff caveat are in the consistency models chapter and are not repeated. What that chapter leaves out is how replicas that missed a write catch up, which happens in three layers.

MechanismWhen it runsWhat it fixesLimits
Read repairDuring a readThe coordinator asks one replica for the data and others for a digest (hash). If they differ it fetches the full data, takes the newest by timestamp and writes it to the stale replicas involved in the read. The client waits for thisOnly repairs keys that are read. Does not happen at consistency level ONE or LOCAL_ONE. Cassandra 4.0 removed the old background (probabilistic) read repair
Hinted handoffWhen a replica is down at write timeThe coordinator stores the write as a hint and replays it when the replica returnsBest effort: Cassandra's docs say hints do not guarantee eventual consistency. By default hints are kept only for a 3-hour window; after that the replica stays stale until repair
Anti-entropy repairOn a schedule, normally started by the operatorReplicas compare Merkle trees (hierarchies of hashes) over their shared token ranges and stream the differencesNot automatic by default (Cassandra 5.0.8 and later have an opt-in repair scheduler). It must run often enough, as the next paragraph explains
replica 1 replica 2 root root range 1 range 2 range 3 range 4 range 1 range 2 range 3 range 4 Root differs, so descend. Only the red path differs, so only range 2 is streamed.
Comparing hashes top down means two replicas holding gigabytes exchange a few hashes and then only the ranges that disagree. A leaf covers a range of keys, not one key, so a mismatch streams that range.

The deadline that makes repair mandatory

Deletes are writes too: Cassandra records a delete as a tombstone and purges it after gc_grace_seconds, 10 days by default. If a replica missed the delete and the tombstone is purged everywhere else before repair reaches it, the old value is still there, and the next repair spreads it back across the cluster as if it were new. The data you deleted comes back. The Cassandra documentation therefore says to repair every node at least once within the grace period, advising every 7 days so that 10 − 7 = 3 days of slack absorb delays, with incremental repair (the default) every 1 to 3 days and a full repair every 1 to 3 weeks as a starting point.

Leaderless stores also need a rule for concurrent versions of one key. The Dynamo paper used vector clocks to detect them and hand both versions back to the application; it truncates a clock when it grows past a threshold (the paper's example is 10 node-and-counter pairs) by dropping the oldest, which the paper concedes can blur the ancestry check. Cassandra chose the simpler rule: every mutation carries a timestamp, taken from the client if it supplies one and otherwise from the coordinator's clock in microseconds, and the highest wins. That is last write wins with all the clock hazards from the dry run above, which is why the Cassandra documentation tells you to run NTP. Monotonic and causal clocks are the subject of the time and ordering chapter.

One more Cassandra detail worth quoting in an interview: blocking read repair gives monotonic quorum reads, so two successive QUORUM reads never go backwards even when a failed write reached only a minority of replicas. The table option read_repair='NONE' turns the write-back off and gives up that guarantee in exchange for partition-level write atomicity.

How the four systems you will be asked about really do it

SystemTopologyDefault durabilityFailure and conflict story
PostgreSQLOne primary, physical streaming standbys; logical replication for selected tablesAsynchronous; synchronous or quorum (FIRST, ANY) by configurationPromotion is a command; the decision is external. Old primary must be rebuilt or rejoin on the new timeline. Logical replication conflicts stop the stream
MySQLOne source with replicas shipping the row-based binary log. Group Replication adds a Paxos-based group, single- or multi-primaryAsynchronous; semi-synchronous waits for one replica's relay log and falls back to async on timeoutGroup Replication elects a new primary and you re-route clients; multi-primary rolls back certification failures
CassandraLeaderless, N replicas per key, replication factor set per datacenter with NetworkTopologyStrategyPer-query consistency level; writes always go to all replicasHints, read repair and anti-entropy repair converge replicas; conflicts resolved by highest timestamp
DynamoDBEach partition has a replication group across Availability Zones using Multi-Paxos, with a leased leader; global tables add RegionsA write is acknowledged once a quorum of the group persists its log record: two of three replicas from different zonesOnly the leader serves writes and strongly consistent reads; any replica serves eventually consistent reads. Cross-Region conflicts: last writer wins, or strong consistency mode

The pattern across all four: a leader-based system decides order in one place and pays at failover; a leaderless system never fails over and pays on every read and in repair; a multi-region system picks between latency and conflicts. Notice that DynamoDB inside a Region looks like a consensus-backed single leader per partition, the shape described in the distributed consensus chapter, and only becomes multi-leader with last writer wins when you ask it to span Regions in its default mode.

Choosing, in one table

If the requirement is…Reach forBecause
Read-heavy, one region, relationalSingle leader, async followersSimplest; accept the failover loss window, or add a quorum standby for zero loss of acknowledged writes
No acknowledged write may ever be lostSynchronous or quorum standby, ideally in another zoneThe RPO is zero but you pay a round trip per commit and need a quorum to stay writable
Low-latency writes in several regionsHome-region routing first; multi-leader only if you mustAvoiding the conflict is cheaper than resolving it
Offline clients or collaborative editingMulti-leader with CRDTs or application mergeConflicts are normal, so make merging a design primitive
Always writable through zone loss, tolerant of stalenessLeaderless with N=3 and a repair scheduleNo failover to botch, at the cost of repair operations and timestamp conflicts
Say it like this → "One leader per shard with two followers in other zones. Commits wait for one of the two followers, so an acknowledged write survives losing the leader, and I only need one of them to be up to keep writing. Reads that must be fresh go to the leader. For failover I'd fence the old leader before promoting, because a false positive with two writers is worse than a few seconds of downtime. If you want multi-region writes I'd first route each user to a home region, and only then talk about resolving conflicts, with increments as counters rather than overwrites."

Recognizing it in an unseen problem

  • Signals: "multi-region", "survive a datacenter loss", "read replicas", "zero data loss", "offline mode", "collaborative editing". Each one is a replication-topology question in disguise.
  • The naive design adds a replica and stops. Ask three follow-ups yourself: is it synchronous, what happens to writes the replica lacks when the leader dies, and who stops the old leader from coming back.
  • Count the loss window. Lag × write rate gives the number of acknowledged writes at risk in an async failover (40 ms × 5,000 per second = 200). A number beats "a few".
  • Multi-leader means conflicts, so say which rule you pick for which field: counters as CRDTs, free text as last-write-wins only if losing an edit is acceptable, uniqueness through a single home or a constraint check, never through eventual convergence.
  • Leaderless means repair. If you pick Cassandra or DynamoDB-style storage, volunteer the repair schedule and the delete-resurrection risk. It signals you have operated one.
  • The pitfall to avoid: calling a replica a backup, or promising "no data loss" while using asynchronous replication.
Before you move on
  • Compute how many acknowledged writes a failover can lose given a lag and a write rate, and say which setting drives it to zero.
  • Explain why a single mandatory synchronous standby lowers write availability, and how a quorum of standbys fixes it.
  • Describe two ways split brain happens during failover and three defences against it.
  • Walk the dry run: why do both regions converge, and what did last-write-wins throw away that a counter CRDT keeps?
  • Name the three layers of Cassandra convergence, and explain why skipping repair can bring deleted data back.
Sources and further reading
  • PostgreSQL: log-shipping standby servers — streaming replication, synchronous replication, FIRST and ANY, promotion, replication slots, hot standby feedback
  • PostgreSQL: logical replication conflicts — which conflicts stop replication and which are applied
  • MySQL 8.4: semisynchronous replication — wait point and the fall back to asynchronous
  • MySQL 8.4: Group Replication limitations — the 9-member limit and SERIALIZABLE in multi-primary groups
  • Cassandra: read repair — blocking read repair, monotonic quorum reads, the read_repair table option
  • Cassandra: hints — best-effort hinted handoff and the 3-hour window
  • Cassandra: repair — Merkle trees, incremental and full repair, the gc_grace deadline
  • DynamoDB global tables: how they work — last writer wins, MREC and MRSC
  • DynamoDB paper (USENIX ATC 2022) — Multi-Paxos replication groups, leader leases, quorum-acknowledged log writes
  • Dynamo paper (SOSP 2007) — vector clocks, merged shopping carts, hinted handoff, Merkle-tree anti-entropy
  • MySQL 8.4: Group Replication multi-primary mode — optimistic execution, certification failures, SERIALIZABLE commits fail
  • GitHub: October 21 post-incident analysis — a 43-second partition, a cross-datacenter failover and 24 hours of reconciliation

Claims in this chapter were checked against these sources in October 2026, for PostgreSQL 18, MySQL 8.4 and Cassandra 5.0. Figures marked "planning" are rules of thumb, not guarantees; the 40 ms lag and the 99.9% machine availability are illustrative inputs.

✓Practise

5 questions drawn from 8, scored out of 5. This is practice: it runs in your browser, saves nothing and does not change what you have marked read.

I5

Finished reading?

0 of 36 chapters read in this series

→Next stop

  1. I4Previous · I4Consistency models
  2. I5you are here
  3. Next · I6Rate limiting & throttlingThe only thing standing between one badly-behaved client and everybody else's latency.19 min read

01On this page

10 sections · 0%

  1. 01Why copy data at all, and why a copy is not a backup
  2. 02Single leader: one place decides the order
  3. 03Synchronous or asynchronous: you are choosing what a crash may cost
  4. 04Failover: promoting a follower is easy, doing it safely is the problem
  5. 05Followers, lag and the operational cost of read replicas
  6. 06Multi-leader: writes in more than one place, and the bill that arrives
  7. 07Leaderless: any replica takes writes, and repair does the cleaning
  8. 08How the four systems you will be asked about really do it
  9. 09Choosing, in one table
  10. 10Recognizing it in an unseen problem

[] chapters · t top