Leader-Based Replication: How It Works
On this page9
In the previous post, we established why databases replicate data: high availability, lower latency, and more read throughput. Now we need to solve the hard part — how do you make sure every replica ends up with the same data?
The most common answer is leader-based replication, also called single-leader or primary-replica replication.
The Leader-Follower Model
The setup is straightforward:
- One replica is designated the leader (also called primary or master). All write requests from clients go to the leader only.
- The remaining replicas are followers (also called secondaries, replicas, or hot standbys). They never accept writes directly.
- Whenever the leader writes to its local storage, it also sends a description of that change to every follower through a replication log (or change stream).
- Each follower applies those changes in exactly the same order as the leader.
- Clients can read from the leader or any follower, but only the leader handles writes.
Leader-based replication
This model is baked into a surprising number of systems you might already use: PostgreSQL, MySQL, MongoDB, Oracle Data Guard, SQL Server AlwaysOn, Kafka, and RabbitMQ — all support it.
The Replication Log
When the leader processes a write, it records what changed and ships that record to followers. What exactly goes in that log depends on the database — we’ll dig into the four main approaches (statement-based, write-ahead log, logical/row-based, and trigger-based) in a later post. For now, the key insight is:
Every follower is essentially replaying the leader’s write history, in order, from the beginning.
As long as a follower processes every entry in the correct sequence, it will end up with an identical copy of the data. This is what makes the model predictable.
Synchronous vs Asynchronous Replication
Here’s where things get interesting. When the leader receives a write, it needs to send that change to its followers — but does it have to wait for them to confirm before telling the client “your write succeeded”?
That question splits replication into two flavours:
Synchronous replication
The leader waits for at least one follower to acknowledge the write before reporting success to the client.
What you get: if the leader suddenly fails, the promoted follower is guaranteed to have an up-to-date copy — no data loss.
What you pay: the write cannot complete until the follower responds. If that follower is slow, overloaded, or unreachable, every write blocks. In practice, making all followers synchronous is usually unworkable — one lagging follower brings writes to a halt for everyone.
Synchronous replication
Asynchronous replication
The leader confirms success to the client immediately, then ships the change to followers in the background.
What you get: writes are fast. The leader can keep processing writes even if followers are falling behind or temporarily offline.
What you pay: if the leader fails before a follower catches up, the writes that hadn’t replicated yet are gone — lost even though the client received a success response. The system trades some durability for speed.
Asynchronous replication
Notice the difference: in the synchronous case, the client is blocked for the full round-trip through the follower. In the asynchronous case, the client gets its confirmation before replication even starts.
The semi-synchronous middle ground
A common production configuration is semi-synchronous: one follower is kept synchronous and the rest are asynchronous.
This guarantees that at least two nodes (the leader plus one follower) always have the latest data — so a single node failure doesn’t mean data loss. At the same time, it avoids the availability problem of requiring all followers to confirm before proceeding.
If the synchronous follower becomes unavailable or slow, another follower is promoted to be synchronous in its place, and the former synchronous follower switches to asynchronous. The cluster always maintains exactly one synchronous replica.
In PostgreSQL this is two settings on the leader:
# postgresql.conf — keep exactly one synchronous follower, whichever
# of the listed standbys is currently connected and caught up.
synchronous_standby_names = 'FIRST 1 (follower_a, follower_b)'
# How far a write must get before COMMIT returns:
# off — don't even wait for the local disk flush
# local — leader's WAL flushed; followers not waited on (async)
# on — at least one synchronous follower has flushed the WAL
# remote_apply — the follower has applied it and will serve it to reads
synchronous_commit = on
remote_apply is the strictest setting and the only one that guarantees a
read on that follower reflects the committed write — at the cost of adding
the follower’s apply time to every commit.
Write flow: semi-synchronous
Fully asynchronous replication
Some systems — especially those that need to stay writable under any conditions — use fully asynchronous replication across all followers. This means the leader can process writes indefinitely, regardless of follower state. The trade-off is real: if the leader fails before replication catches up, those writes are gone even though clients were told they succeeded.
Whether this trade-off is acceptable depends on the workload. Losing a few seconds of writes might be acceptable for a social media timeline; it’s not acceptable for a financial transaction log.
Write flow: fully asynchronous
Key Takeaways
- The leader-follower model concentrates all writes on a single node and fans changes out to replicas through a replication log.
- Followers apply the log in order, making them consistent copies of the leader.
- Synchronous replication is durable but adds latency to every write.
- Asynchronous replication is fast but risks losing recent writes if the leader fails.
- Semi-synchronous (one sync follower, rest async) is the practical middle ground most databases offer.
In the next post, we’ll look at what happens when things go wrong: adding a new follower to a running cluster, and recovering from leader and follower failures.
References
- Martin Kleppmann, Designing Data-Intensive Applications, chapter 5 — the canonical treatment of replication this series works through.
- PostgreSQL manual — Log-Shipping Standby Servers, covering streaming replication and the synchronous/asynchronous switch.
- MySQL manual — Replication Formats.