System DesignPublished 2/23/2026

Replication: Copying Your Database, Without Sacrificing Performance or Consistency

Starting from the fact that a single database can neither handle heavy traffic nor survive a failure, this post digs into how replication spreads data across multiple machines to ease that load, and the consistency tradeoffs behind leader-follower architecture, synchronous vs. asynchronous replication, and failover.

What replication actually does

Replication means keeping the same data on multiple machines, all kept in sync with each other. That gives you two immediate wins:

  • Spread the load: read traffic doesn't have to hit one machine — it can be split across several replicas.
  • Higher availability: if one machine goes down, the others still have the full data set, so a single hardware failure doesn't take the whole service down.

Sounds simple enough — just "copy the data." But the moment the same data lives in more than one place, a new question shows up: how do you keep all those copies in sync? When you write, do you wait for every replica to finish writing before calling it done, or do you respond as soon as one machine has it?

Leader-follower: the architecture you'll see most

Most databases implement replication with a leader-follower setup: one machine is designated the leader, and the rest are followers (also commonly called replicas). The rules are simple:

  • All writes go to the leader, and only the leader.
  • The leader forwards every write to all the followers, which apply the same change.
  • Reads can be served by the leader or by any follower.
js
// writes only hit the leader; reads get spread across followers
async function createOrder(order, leaderDb) {
  await leaderDb.write('orders', order) // writes can only go through the leader
}
 
async function getOrder(orderId, followerDb) {
  return followerDb.read('orders', orderId) // reads can be handed to any follower
}

What makes this architecture so workable is that it splits writes and reads into two separate paths. Writes stay simple — there's exactly one place they can happen, so you never have to deal with multiple writers stepping on each other. Reads, meanwhile, can be freely distributed, since every follower is, in theory, holding a complete copy of the data. The read replicas mentioned in the scalability post are exactly the followers in this kind of setup.

Synchronous vs. asynchronous replication

When the leader forwards a change to its followers, it can do so two ways — the difference comes down to whether the leader waits for followers to confirm.

Synchronous replication: after receiving a write, the leader waits until the followers have applied that change too before telling the caller "write succeeded." The upside is that once you get a success response, every replica is guaranteed to be consistent. The downside is that write latency gets dragged down to whatever the slowest follower can manage — the caller is stuck waiting until that follower responds.

Asynchronous replication: the leader writes its own copy and responds immediately, without waiting on followers. Followers catch up in the background at their own pace. The upside is write speed — it's never held back by a follower. The downside is a gap between the leader and its followers, known as replication lag.

Most systems choose asynchronous replication to get that performance win, which means accepting a hard truth: data read from a follower might not be the latest version.

The weirdness replication lag causes

Say a user just updated their display name on your site. The write hits the leader, which immediately responds with success. The page refreshes right after, and the request to fetch that name gets routed to a follower that hasn't caught up yet — so the screen shows the old name. The user's first reaction is usually "I just changed this, why did it revert?" But nothing actually broke — the follower just hasn't synced yet.

This shows up in the literature under a couple of names:

  • Read-your-writes consistency: a user should immediately see the result of their own write. Common fixes are routing reads for data a user just wrote straight to the leader, or tracking the timestamp of a user's last write and making sure any follower serving them has caught up to at least that point.
  • Eventual consistency: no guarantee of immediate consistency, but a guarantee that if no new writes come in, all replicas will eventually converge on the same data. Most systems running asynchronous replication are, in practice, leaning on exactly this assumption.

In other words, choosing asynchronous replication means trading brief data inconsistency for write performance — whether that trade is worth it depends on whether your use case can tolerate that window of staleness.

What happens when the leader goes down: failover

Leader-follower solves the read-scaling problem, but writes are still concentrated on a single machine — the leader. Once that machine goes down, writes stop cold. That's exactly the scenario failover is built to handle:

  1. The system detects that the current leader isn't responding, usually through periodic health checks.
  2. Among the remaining followers, it picks the one with the most complete, up-to-date data and promotes it to be the new leader.
  3. The other followers switch to following the new leader, and clients redirect their writes there too.

That sounds clean on paper, but it hides some real traps in practice. If the setup was using asynchronous replication, the old leader may have accepted a few writes right before it died that never made it to any follower — that data is simply gone. And if the old leader later comes back online, it's still holding onto data the new leader never received, so the two now disagree with each other. Sorting out that conflict — detecting it and deciding whose version wins — takes extra machinery. That's why failover is never as simple as flipping a switch.

Multi-leader: writes from more than one place

Leader-follower assumes writes only ever happen in one place, but that assumption breaks down in some scenarios — say your service runs out of data centers in multiple regions, and each region wants its users writing to something nearby instead of sending every write halfway around the world to a single leader. That's where multi-leader replication comes in: each region runs its own leader, and the leaders sync with each other.

Multi-leader replication fixes the write-latency problem, but it introduces a headache leader-follower never has to deal with: when two leaders get conflicting writes to the same record at nearly the same time, whose version wins? Say the Taipei leader sets a product's stock to 10, and almost simultaneously the Tokyo leader sets the same stock to 8 — both writes succeed locally, and the conflict only surfaces once the two leaders sync up. Common resolutions include last-write-wins, punting the decision to the application layer, or designing data structures that let both changes merge automatically. Whichever approach you pick, it's added complexity — which is exactly why most systems skip multi-leader replication unless they have a hard requirement for cross-region writes.

Which one to use comes down to tradeoffs

By this point it's clear that every choice in replication is a tradeoff: synchronous replication buys consistency, asynchronous buys performance; leader-follower keeps things simple but bottlenecks writes on one machine, while multi-leader spreads out writes but has to deal with conflicts. There's no universally optimal setup — which one you pick depends on whether your system can tolerate brief inconsistency, how low your write latency needs to be, and whether you need to support simultaneous writes across regions. Just like the tradeoffs covered in scalability, an architecture that can absorb more traffic or survive more failures is usually also a more complex one — how much of that complexity is worth taking on comes down to what your actual use case needs.

Wrapping up

Replication copies data across multiple machines to solve two problems at once: spreading out read load and surviving single-machine failures. Most systems use a leader-follower architecture, concentrating writes on the leader and spreading reads across followers, and the choice between synchronous and asynchronous replication decides whether the system sacrifices performance or consistency. Asynchronous replication's replication lag means users can briefly read stale data, which needs mechanisms like read-your-writes consistency to paper over. And when the leader fails, failover can lose data or produce conflicts precisely because of that same lag.