Skip to main content

Read Scaling with Replicas

Level 3: Level 3: Scaling the Data Tiermedium30 minreplicationread-replicasscaling

Single-leader replication scales reads linearly but never writes; pick async/sync/semi-sync by durability vs latency, watch lag, and shard only when writes outgrow one leader.

The first, cheapest lever for a read-heavy database

When a read-heavy database saturates one machine, replication is the first lever you reach for, before any sharding, because it is operationally cheap and non-disruptive. The dominant pattern is single-leader (primary/replica) replication: every write goes to one leader, the leader streams its change log to N followers, and reads fan out across the followers. This scales reads linearly with follower count. It does not scale writes: every follower must apply every write, so the leader's write throughput is still the ceiling. That asymmetry is the whole point to internalize. Adding replicas buys read capacity and read-path fault tolerance, nothing more.

Check yourself
Your write throughput is at 90 percent of what the leader can absorb. You add three more read replicas. What happens to write capacity?

How the leader waits for followers

The core tradeoff trades durability and read freshness against write latency:

  • Asynchronous: the leader commits and acks the client without waiting for any follower. Lowest write latency, highest throughput, but if the leader dies before a write reaches a follower, that write is lost, and followers can lag arbitrarily.
  • Synchronous: the leader waits for a follower to confirm before acking. No data loss on leader failure for the confirmed write, but write latency now includes a round trip, and if the sync follower stalls, writes block entirely.
  • Semi-synchronous (the usual production choice): exactly one follower is synchronous and the rest are async. You get "the write survives on at least two nodes" durability without gating on all of them.

The number you must instrument is replication lag: how far behind, in seconds or bytes/LSN, each follower is. Under async replication lag is usually milliseconds but spikes to seconds under write bursts, long-running follower queries, or network hiccups. Lag is what makes replica reads stale, and stale reads are the source of the session-guarantee bugs covered later in this module. Route lag-sensitive reads (a user checking data they just wrote) to the leader or to a follower whose lag you have bounded.

Adding capacity online

Provision a new follower, let it restore from a snapshot and catch up from the leader's log, then add it to the load balancer's pool once its lag is near zero. No downtime, no application change. This is how you take a CPU-bound primary from "melting" to "comfortable" in an afternoon.

Interview nuance: be crisp about when replication stops helping. It stops when (a) write throughput exceeds one leader (every replica already does all the writes, so more replicas do not help), or (b) the dataset no longer fits or fits poorly on one node. Both force sharding. Replicas also do not remove the leader as a single point of failure for writes: you need automated failover (Patroni, Orchestrator, or a managed service) to promote a follower, and that introduces its own split-brain and lost-write risks.

        writes            +--> follower 1 --\
client --------> LEADER --+--> follower 2 ---+--> read LB --> reads
                          +--> follower 3 --/
   writes bottleneck at leader; reads scale with follower count

Recap: single-leader replication scales reads by fanning them across followers but never scales writes; choose async, sync, or semi-sync by trading write latency against durability and staleness, watch replication lag, add followers online for zero-downtime read capacity, and shard once writes or dataset size outgrow one leader.

Check yourself
A product's database is melting and your first instinct is 'add replicas'. In which situation does that instinct actually fix the problem?

Apply

Your turn

The task this lesson builds to.

Design the read path for a product catalog serving 50k read QPS against a single Postgres primary that is CPU-bound; show how you add capacity without downtime.

Think about

  1. How does single-leader replication scale reads but not writes?
  2. What is the durability/latency tradeoff of sync vs async replication?
  3. When does replication stop helping and force sharding?

Practice

Make it stick

A second problem on the same idea, so it survives past today.

Design the read-scaling strategy for Shopify-style storefront reads where a flash sale drives 300k read QPS against product and inventory tables, replicas can lag up to 4 seconds during the write burst, and overselling inventory is a hard financial constraint.

Think about

  1. Which fields tolerate 4 seconds of staleness and which cannot tolerate any?
  2. How does a conditional atomic decrement make correctness independent of read freshness?
  3. What absorbs most of the 300k QPS before it ever reaches a replica?