What it's for
- Most apps read far more than they write. Replicas move the reads: the primary keeps the writes, the copies keep the answers.
- The CDN chapter copied static objects outward; here the copies are of changing state, fed by the primary's write log — which is why versions and lag matter.
- The load balancer chapter spread requests across identical servers; replication is the data version of the same instinct — but copies of changing data can disagree, which is where the design gets interesting.
Good to know
Shown is single-leader replication with asynchronous log shipping — the PostgreSQL/MySQL default family, one design among many. The write's acknowledgment here is primary-only: the client hears "done" before any replica has the change, and receiving a log record is not applying it — a replica can hold the record and still serve the old value until it applies. A crash after an async ack but before the stream lands can lose that acknowledged write. That stream creates the lag window — a read that lands on a not-yet-updated replica sees the old value, which is why "read your own writes" is a feature you have to build (route the writer's reads to the primary, track a position in the log, or wait). Synchronous replication narrows the window by confirming the write only after a replica acknowledges — the third sandbox replay uses a one-replica ack — at the cost of slower, less available writes; and even then only that replica is current, not every read everywhere. Replicas scale eligible reads, not writes: every write still funnels through the one primary (splitting writes is the sharding chapter), and a replica read isn't faster, just spread. Replication lag is also not cache expiry: the copy updates when the log record applies, not on a timer. Replicas are a read-scaling and availability tool, not backups: a mistaken delete streams to every copy just as faithfully. Not shown: failover, which is only safe with leader election, fencing (so the old primary can't still accept writes) and catch-up — promoting a stale replica without them can lose acknowledged writes or split the brain; and multi-primary setups.
How it works, step by step
Why the steps go in this order
- The bottleneck comes first: one database doing every read and every write.
- Read-heavy traffic is the opportunity — if most asks are reads, most asks can be moved.
- Copies appear only then, so their job is obvious: the same data, nearer the reads.
- The write path comes before the read path, because the stream from primary to replicas is what makes the copies true.
- The lag window and read-your-writes come last: spreading reads is easy; knowing when a copy is wrong is the design.
Before you rely on it
This is a toy: one primary, two replicas, hand-set traffic ("9 reads : 1 write") and hand-set lag; version and log counters (#41–#43) are the toy's own state, not benchmarks. Real lag varies with load, network and replica count, from milliseconds to seconds and beyond — nothing here is a measurement. "Reads spread across replicas" assumes the app routes them there; proxies, drivers and consistency needs decide that in practice. The cited sources describe production systems with their own measured behavior.
References
- PostgreSQL docs — high availability, load balancing and replication
- Designing Data-Intensive Applications (Kleppmann) — chapter 5, replication: leaders, followers, lag
- RFC 9111 is two chapters back; here the consistency problem is the app's, not HTTP's
- CDN — the previous chapter: copies at the edge, and the same freshness question