Building Blocks · Databases and Replication

Replication and Choosing a Data Store

SQL or NoSQL for a workload, leader-follower replication, synchronous versus asynchronous, replication lag and read-your-writes, and failover.

  • 9 min read
  • 11 practice questions
On this page
  1. Description
  2. Choosing a data store first
  3. Leader-follower replication
  4. Synchronous or asynchronous
  5. Replication lag
  6. Failover
  7. Read replicas for read scaling
  8. Which setup?
  9. Check yourself
  10. Key takeaways
  11. Quick revise
  12. Practice

Description

Every system design has a box labelled "database", and two questions decide most of what happens inside it: which kind of database fits the data, and how many copies of it you keep. This lesson is about both.

Picture an app on one PostgreSQL server. Reads have grown to 90% of the load and the CPU is pegged; worse, a disk failure last month meant restoring from a nightly backup - and losing a day of orders. Two problems, one tool: replication, keeping copies of the data on several machines. But copies bring problems of their own: which copy is right, and what does a user see when the copies disagree? Step by step:

  1. Choosing a data store from the way you read and write.
  2. Leader-follower replication.
  3. Synchronous versus asynchronous copies.
  4. Replication lag, and the odd things users see because of it.
  5. Failover, and the danger of two leaders.
  6. Which setup for which need.

Choosing a data store first

Before replication, the right store for the job. Start from the access patterns:

WorkloadGood fitWhy
Orders, payments, inventory - joins, constraints, multi-row transactionsRelational (PostgreSQL, MySQL)ACID transactions, flexible queries
Sessions, carts, profiles read by ID at huge scaleKey-value (DynamoDB, Redis)Fast lookups by key, easy to partition
Metrics, events, messages - heavy appends read by key and time rangeWide-column / time-series (Cassandra, a TSDB)Writes spread across nodes; range scans within a partition
Self-contained records with varying fieldsDocument (MongoDB)The record is one document
Full-text searchSearch index (Elasticsearch)Built alongside the source of truth, not instead of it
Photos, video, backupsObject store (S3)Cheap, durable blobs; the database holds the metadata

"NoSQL scales, SQL doesn't" isn't a reason. A relational database handles tens of thousands of transactions per second on one node and can be sharded; a key-value store gives up joins and (often) multi-item transactions to partition easily. Choose by what you read, how you write and which guarantees you need.

Leader-follower replication

One node is the leader: every write goes there. It records each change in a log and streams it to followers (replicas), which apply the changes in order.

writes

reads that can be slightly stale

reads

change log

change log

App servers

Leader

Follower 1

Follower 2

writes

reads that can be slightly stale

reads

change log

change log

App servers

Leader

Follower 1

Follower 2

  • Reads can go to followers, so read capacity grows with each replica.
  • Writes still all go to the leader - replicas don't scale writes; sharding does.
  • If the leader dies, a follower is promoted to be the new leader.

Synchronous or asynchronous

SynchronousAsynchronous
Write acknowledged afterA follower has the change tooOnly the leader has it
Leader failsNo acknowledged write is lostThe last writes may be lost
Write latencyHigher - waits for a follower round tripLower
A follower is slow or downWrites stallWrites carry on; the follower lags

A common middle ground is semi-synchronous: one follower synchronous (so every acknowledged write exists on two machines), the rest asynchronous.

Replication lag

Asynchronous followers run behind - usually by milliseconds, but by seconds or minutes when they're overloaded or catching up. That creates anomalies users notice:

FollowerLeaderUserFollowerLeaderUserUPDATE name = 'Ava T.'OKreplicate (still in flight)reload profilename = 'Ava' (old)
FollowerLeaderUserFollowerLeaderUserUPDATE name = 'Ava T.'OKreplicate (still in flight)reload profilename = 'Ava' (old)
  • Reading your own writes. A user changes their display name, the page reloads from a follower that hasn't got the change yet, and the old name is back. Fix: read a user's own recent writes (say, for a minute after a change) from the leader, or remember the log position of their last write and read from a follower that has reached it.
  • Monotonic reads. A user refreshes twice and hits two followers: a new comment appears, then disappears. Fix: pin each user's reads to one follower (for example by hashing the user ID).

Lag is also why "read from a replica" is wrong for anything a decision depends on - the stock count at checkout, a balance before a payment.

Failover

When the leader fails, something must notice (health checks with a timeout), choose the most up-to-date follower, promote it, and point writes at it. The dangers:

  • Lost writes. With asynchronous replication, writes the old leader acknowledged but hadn't shipped are gone once a follower is promoted.
  • Split brain. The old leader was only unreachable, not dead. It comes back still believing it's the leader and accepts writes - now two leaders diverge. Failover must fence the old leader (revoke its access, or reject writes carrying an old leadership epoch).
  • Timeouts. Too short and a GC pause triggers an unnecessary failover; too long and writes are down for longer.

Read replicas for read scaling

For a read-heavy app (90% reads), adding read replicas is usually the first scaling step: cheap, no application sharding, and it doubles as failover capacity. Route queries that can tolerate slight staleness to replicas, and the rest (and all writes) to the leader.

Which setup?

NeedSetup
More read capacityAsynchronous read replicas
Never lose an acknowledged writeAt least one synchronous (or quorum) follower
Survive a zone failureA follower in another zone, automated failover with fencing
Survive a region failureCross-region replica (asynchronous: accept some loss) and a tested promotion runbook
More write capacitySharding (the next skill), not replicas
Reads that a decision depends onThe leader

Going further. The deep dive (next tab) covers how replication is implemented (physical versus logical), leaderless quorums and their math, multi-leader conflicts and why last-write-wins loses data, consensus (Raft) and how it prevents split brain, RPO and RTO, and the storage engines underneath - B-trees versus LSM trees.

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Why don't read replicas help a write-bound database?

Show answer

Every write still goes to the one leader - and every replica must apply every write too. Replicas multiply read capacity; to scale writes you partition (shard) the data.

2. A user posts a comment and immediately sees the page without it. What's likely happening, and one fix?

Show answer

The page read came from an asynchronous follower that hasn't received the write yet (replication lag). Read the user's own recent writes from the leader, or wait for a follower that has caught up to the write's log position.

3. After a failover the old leader rejoins and keeps accepting writes. What is this called, and how is it prevented?

Show answer

Split brain - two nodes both acting as leader, with diverging data. Failover fences the old leader: its writes are rejected (for example by a leadership epoch the storage checks) or its access is revoked before the new leader starts.

Key takeaways

  • Choose the store by access pattern and guarantees, not by slogan.
  • Leader-follower: writes to the leader, reads from followers, promote a follower on failure.
  • Synchronous replication: no loss, slower writes, stalls on a stuck follower. Asynchronous: fast, can lose the last writes.
  • Lag breaks read-your-writes and monotonic reads - route accordingly.
  • Failover must fence the old leader to avoid split brain.
  • Replicas scale reads; sharding scales writes.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before a design interview, and open the full lesson for anything that doesn't ring a bell.

Pick the store by access pattern

WorkloadGood fit
Orders, payments, inventory - joins, constraints, transactionsRelational (PostgreSQL, MySQL)
Sessions, carts, profiles read by ID at huge scaleKey-value (DynamoDB, Redis)
Metrics, events, messages - heavy appends, read by key and timeWide-column / time-series (Cassandra, a TSDB)
Self-contained records with varying fieldsDocument (MongoDB)
Full-text searchSearch index, built from the source of truth
Photos, video, backupsObject store (S3); metadata in the database

"NoSQL scales, SQL doesn't" is not a reason - choose by reads, writes and guarantees.

Pick the replication setup

NeedSetup
More read capacityAsynchronous read replicas
Never lose an acknowledged writeA synchronous (or quorum) follower, or consensus
Survive a zone failureA follower in another zone + automated failover with fencing
Survive a region failureCross-region replica (async: some loss) + a tested promotion runbook
More write capacitySharding - replicas don't scale writes
Reads a decision depends onThe leader
SynchronousAsynchronous
Acknowledged afterA follower has it tooOnly the leader has it
Leader failsNothing acknowledged lostLast writes may be lost
Slow followerWrites stallFollower lags

Semi-synchronous: one sync follower, the rest async.

The traps

  • Read-your-writes: a user's change vanishes on reload from a lagging follower - read their recent writes from the leader, or wait for the write's log position.
  • Monotonic reads: a comment appears then disappears across two followers - pin a user to one follower.
  • Split brain: a deposed leader comes back still accepting writes - fence it (revoke access, reject old epochs).
  • Failover timeouts: too short fails over on a GC pause; too long extends downtime.
  • Replicas as backups: a replica copies DROP TABLE in milliseconds.

Staff-level points, one line each

  • Shipping changes: statement-based (breaks on now()), physical WAL (exact copy, same version), logical row changes (selected tables, across versions - enables zero-downtime upgrades and CDC).
  • Leaderless quorums: W + R > N makes every read overlap every write. N=3: W=2/R=2 yes, W=1/R=1 no; N=5 with W=2 needs R ≥ 4 (or balance at 3/3).
  • Read repair, Merkle-tree anti-entropy, hinted handoff - and sloppy quorums quietly drop the W + R > N guarantee during outages. Quorums aren't transactions.
  • Multi-leader conflicts: last-write-wins loses data, and clock skew makes the "last" wrong (Dublin 5 ms fast beats Austin's later write). Prefer home-region ownership, CRDTs, or app-level merge.
  • Consensus (Raft, Paxos): commit on a majority, elect by majority, terms fence old leaders - no lost acknowledged writes, but no writes without a majority.
  • Cluster availability at 99% per node: 3 nodes 99.970%, 4 nodes 99.941% (worse), 5 nodes 99.999% (tolerates 2). Use odd sizes. Patroni uses etcd/Consul because PostgreSQL has no built-in consensus.
  • RPO = data you can lose (async: the worst lag, not the average); RTO = time to recover (restoring 2 TB at 200 MB/s ≈ 2.8 h before WAL replay). Point-in-time recovery from base backup + archived WAL is what undoes a bad DELETE; test restores.
  • B-tree (in-place pages; good for mixed read-heavy, transactional; needs vacuum) vs LSM (memtable → sorted files → compaction; great write rates; compaction stalls and disk spikes).

Say it in an interview

  • "90% reads, so read replicas first - writes stay on one leader until the write rate says shard."
  • "Profile edits are read from the leader for a minute afterwards, so users see their own change."
  • "Failover is automated with fencing, so the old primary can't keep writing after it's deposed."
  • "Replicas aren't backups - PITR covers the bad DELETE, and we drill restores."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Replication and Choosing a Data Store free

Practice Replication and Choosing a Data Store free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime