Database Replication
Replication keeps copies of your data on several machines for availability and read capacity. Learn leader-follower and multi-leader setups, synchronous vs asynchronous copies, replication lag and failover.
In a nutshell
- Leader-follower: all writes go to the leader, which streams changes to followers that serve reads.
- Asynchronous replication is fast but a failover can lose recent writes; synchronous waits for a copy, adding latency.
- Replication lag means a follower can be behind: users may not see their own changes unless you route carefully.
- Multi-leader and leaderless setups accept writes in several places, at the cost of resolving conflicts.
Leader and followers
Leader-follower replication
All steps Writes go to one leader. Followers apply its change log and serve reads.
- Every write goes to the leader.
- The leader streams its change log to the followers, which apply it in order.
- Reads can go to followers, spreading load across machines.
Diagram as text
- Every write goes to the leader.
- The leader streams its change log to the followers, which apply it in order.
- Reads can go to followers, spreading load across machines.
- More read capacity: most apps read far more than they write; add followers to serve the reads.
- Availability: if the leader dies, a follower is promoted (failover).
- Locality: put a follower near users in another region for fast local reads.
- Safe heavy queries: run analytics and backups on a follower without slowing the leader.
Synchronous or asynchronous
| Synchronous | Asynchronous | |
|---|---|---|
| Commit waits for | At least one follower to confirm | Only the leader's own disk |
| Write latency | Higher (a network round trip) | Lowest |
| Leader dies | No committed data lost | Writes not yet copied are lost |
| Follower slow or down | Writes stall (unless another follower confirms) | No effect on writes |
Replication lag
Asynchronous followers are usually milliseconds behind, but under load or network trouble it can be seconds or more. That causes visible bugs:
Where did my comment go?
All steps The write reached the leader, but the read went to a follower that had not caught up yet.
- The user posts a comment; it is written to the leader.
- The leader confirms.
- The page reloads and reads from a follower.
- The follower is a moment behind and does not have the comment.
- The change arrives shortly after, but the user already thinks it was lost.
Diagram as text
- The user posts a comment; it is written to the leader.
- The leader confirms.
- The page reloads and reads from a follower.
- The follower is a moment behind and does not have the comment.
- The change arrives shortly after, but the user already thinks it was lost.
Fixes for read-your-own-writes: read from the leader for anything the user just changed (or for a few seconds after any write by that user), or track the log position of the user's last write and only use followers that have reached it.
Route a user's reads to the leader for a short window after they write
import java.util.*;
class ReadRouter {
private final double stickySeconds;
private final Map<String, Double> lastWrite = new HashMap<>();
ReadRouter(double stickySeconds) {
this.stickySeconds = stickySeconds;
}
synchronized void recordWrite(String userId, double now) {
lastWrite.put(userId, now);
}
synchronized String readTarget(String userId, double now) {
Double last = lastWrite.get(userId);
if (last != null && now - last < stickySeconds) {
return "leader";
}
return "follower";
}
}import threading
class ReadRouter:
def __init__(self, sticky_seconds):
self.sticky = sticky_seconds
self.last_write = {} # user id -> time of their last write
self.lock = threading.Lock()
def record_write(self, user_id, now):
with self.lock:
self.last_write[user_id] = now
def read_target(self, user_id, now):
with self.lock:
last = self.last_write.get(user_id)
if last is not None and now - last < self.sticky:
return "leader"
return "follower"Failover and multi-leader
Failover sounds simple (promote a follower) but has sharp edges: detecting that the leader is really dead and not just slow, choosing the most up-to-date follower, redirecting writes, and making sure the old leader does not come back still thinking it is the leader (split brain). Managed databases automate this, usually in tens of seconds.
Multi-leader replication accepts writes in several places (for example one leader per region) and syncs them. Writes are fast everywhere, but two leaders can change the same record at once, so you need a conflict resolution rule: last write wins (loses data), merge the values, or let the application decide. Leaderless systems (Dynamo-style, such as Cassandra) write to several replicas and use quorums instead.
Common mistakes
- Reading from followers right after a write and showing users stale data.
- Treating followers as backups: a bad DELETE replicates to all of them instantly. Keep real backups too.
- Assuming failover loses nothing while using asynchronous replication.
- Choosing multi-leader without a plan for conflicts.
Interview questions
Try answering out loud before you open each one.
Reads are overloading the database. What do you do?
Add a cache for hot reads and add read replicas, routing read-only queries to them. Handle replication lag: read-your-own-writes from the leader, and keep queries needing fresh data on the leader. If writes are the bottleneck, replicas do not help; look at sharding.
What happens when the leader fails?
Failure is detected (missed heartbeats), the most up-to-date follower is promoted, clients are redirected (DNS, proxy or a config service), and the old leader is fenced off so it cannot accept writes if it returns. With asynchronous replication, writes not yet copied may be lost.
Check yourself
Related topics
Further reading
- PostgreSQL documentation: High availability, load balancing, and replication PostgreSQL
- Working with DB instance read replicas Amazon RDS documentation
Your notes
Saved in this browser as you type.
Finished this topic?
Mark it read to track your progress, then carry on with the next one.