Replication: leaders, followers and copies

Big data systems keep several copies of everything, so that a dead disk at 2 am means seconds of downtime instead of lost data. In this lesson you learn how leaders and followers stay in sync, why “acknowledged” doesn't always mean “safe”, what Kafka's acks=all guarantees, and how majorities and fencing tokens stop two leaders from taking over at once.

Module 3 · Distributed Systems Concepts⏱ 30 minBeginner → AdvancedRuns in your browser (Python)3 real-time scenariosReplication simulator on your PC9 practice problems
1 The story

2:13 am: “orders-db primary down”

On the internship’s on-call channel at 2:13 am an alert fires: “orders-db primary down”. Twenty-eight seconds later: “failover complete, replica-1 promoted”. In the morning Kabir reads the incident note. One line worries him: “1 order acknowledged in the last second before the crash needs manual reconciliation.”

02:13 amLeader DB✗ disk failurefailoverFollower 1promoted to leaderFollower 2now follows F1Orders appdown for 28 s1 order to re-check Because copies existed, a dead disk meant 28 seconds of downtime, not a lost business. myphatshala.in
Kabir

Sir, the database died and the app came back in 28 seconds. How? And how can an order be “acknowledged” and then go missing?

Arjun Sir

Because the data was replicated: the same data was kept on three machines. One, the leader, takes all writes; the two followers copy everything it does. When the leader died, a follower was promoted.

Riya

So why was one order missing?

Arjun Sir

Because the followers copy slightly later, a fraction of a second behind. The leader had said “OK” to that order before any follower had copied it. That is asynchronous replication: fast, but a crash can lose the last moment of writes.

Kabir

Then why not wait for the followers every time?

Arjun Sir

That’s synchronous replication: safer, but every write waits for the slowest copy. Today you’ll see this trade-off, watch a failover step by step, learn what Kafka’s acks=all really means, and see the scariest failure of all: two leaders at once, called split brain.

2 Definition

What is replication?

Formal definition (write this in exams)

Replication is maintaining copies of the same data on multiple nodes to provide fault tolerance, high availability, durability, read scalability and lower latency. In leader-based (primary–replica) replication one node accepts writes and streams changes to followers; replication can be synchronous (the write is acknowledged after replicas confirm), asynchronous (acknowledged immediately, replicas apply later) or semi-synchronous. Multi-leader and leaderless replication allow writes at several nodes and must resolve conflicts. The number of copies is the replication factor.

In simple words

Replication means keeping the same data on several machines. Usually one machine (the leader) takes the changes and the others (followers) copy them. If the leader breaks, a follower takes over. Copies can be updated straight away (safe but slower) or a moment later (fast but a crash can lose the last few changes).

Words you’ll meet in this lesson

Leader / primaryThe node that accepts writes and sends changes to the others.
Follower / replicaA node that keeps a copy by applying the leader’s changes.
Replication logThe ordered list of changes (for example a write-ahead log) that followers replay.
Replication lagHow far behind a follower is, in seconds or in log entries.
FailoverPromoting a follower to leader when the leader fails.
Split brainTwo nodes both acting as leader at the same time.
QuorumThe minimum number of nodes that must agree for a read or write to count.
RPO / RTOMaximum acceptable data loss / downtime after a failure.

Replication in tools you will use

HDFSevery block stored 3 times by default, on different racks where possible
Kafkaeach partition has a leader and followers; in-sync replicas (ISR); producers choose acks=0, 1 or all
PostgreSQL / MySQLprimary with streaming read replicas; sync or async; managed services automate failover
Cassandraleaderless; replication factor per keyspace; consistency level chosen per query
Cloud object storagecopies or erasure-coded pieces across availability zones, handled for you

Replication at three levels

Pick your level. New to this? Start at Beginner and climb.

Beginner Photocopies of the class notes

  • Replication is keeping copies of the same data on several machines, like photocopying the topper’s notes for three friends. If one copy is lost, the others still have it.
  • Why: survive failures (availability), never lose data (durability), let more people read at once (read scaling), and keep copies close to users (lower latency).
  • Leader and followers: one person writes the notes (the leader); the others copy from them (followers). Everyone asks the leader to change something.
  • Not a backup: if you delete a page by mistake, the deletion is copied too. Replication protects against machines failing, backups against mistakes.

Intermediate Sync vs async, lag and read replicas

  • Synchronous: the leader confirms a write only after followers have it. No loss on leader failure, but writes are slower and a slow follower slows everyone.
  • Asynchronous: the leader confirms immediately and followers catch up later. Fast, but the last moments of writes can be lost in a crash, and followers lag behind.
  • Semi-synchronous: wait for one follower, not all. A common middle ground.
  • Replication lag: a read from a follower may show old data. Problems this causes: a user doesn’t see their own update (read-your-writes), or sees data jump backwards when reads hit different replicas (monotonic reads).
  • Replication factor: how many copies. HDFS blocks: 3. Kafka partitions: commonly 3, with min.insync.replicas=2 and producers using acks=all.

Advanced Failover, split brain and consensus

  • Failover: detect that the leader is dead (heartbeat timeouts), choose the most up-to-date follower, promote it, and redirect clients. Too short a timeout causes needless failovers; too long means longer outages.
  • RPO and RTO: Recovery Point Objective = how much recent data you can afford to lose (async replication: seconds); Recovery Time Objective = how long you can be down (automatic failover: tens of seconds).
  • Split brain: a network partition makes the old leader and a newly elected one both accept writes. Prevent it with majority quorums (only the side with more than half the nodes can elect a leader) and fencing tokens (increasing epoch numbers; storage rejects writes from older epochs).
  • Consensus: algorithms like Raft and Paxos (used in etcd, ZooKeeper and Kafka’s KRaft) let nodes agree on one leader and one order of writes despite failures.
  • Multi-leader and leaderless: several nodes accept writes (multi-region apps, Cassandra/Dynamo-style quorums with R + W > N). Concurrent writes conflict and must be resolved: last-write-wins (can silently drop data), version vectors, or CRDTs that merge automatically.

Exam tip: Define replication, list its benefits (availability, durability, read scaling, latency), and compare synchronous vs asynchronous in a table (latency, data-loss risk, availability). Name the three architectures (single-leader, multi-leader, leaderless) with one example each, and mention replication lag and failover.

3 Types and ways to use it

Leaders, followers and how they sync

Single-leader

One leader takes all writes; followers copy and can serve reads. Simple and consistent ordering. PostgreSQL, MySQL, Kafka partitions, HDFS NameNode HA.

Most common

Multi-leader

Several leaders (often one per region) accept writes and sync with each other. Good for multi-region apps; conflicts must be resolved.

Multi-region

Leaderless

Clients write to several replicas and read from several; quorums (R + W > N) give consistency. Cassandra, DynamoDB-style stores.

Quorums

Synchronous vs asynchronous

SynchronousAsynchronousSemi-synchronous
Write acknowledgedAfter all chosen replicas confirmImmediately by the leaderAfter at least one replica confirms
Write latencyHighest (waits for slowest)LowestMedium
Data loss if leader diesNoneLast moments of writesNone if that replica survives
Effect of a slow replicaSlows every writeOnly increases lagTolerates slow extra replicas
Typical usePayments within one regionRead replicas, cross-region copiesDefault for many critical databases

Replication is not a backup. A bad DELETE or a bug that corrupts rows is replicated to every copy within seconds. Keep point-in-time backups or snapshots too, and test restoring them.

4 Step by step

One write, three copies, one failure

  1. The leader writes and acknowledges

    leader, followers = [], {"F1": [], "F2": []}
    def write(entry):
        leader.append(entry)            # 1. leader appends to its log
        return "OK"                     # 2. async: acknowledge immediately
    print(write("order O1"), write("order O2"))
    print("leader:", leader, "| F1:", followers["F1"])
    OK OK leader: ['order O1', 'order O2'] | F1: []
    Every write goes to the leader, which appends it to its replication log. With asynchronous replication it says “OK” right away, before any follower has the change.
  2. Followers replay the log

    leader = ["order O1", "order O2"]
    followers = {"F1": [], "F2": []}
    for f in followers:                 # 3. followers copy the log in order
        followers[f].extend(leader)
    print(followers)
    {'F1': ['order O1', 'order O2'], 'F2': ['order O1', 'order O2']}
    Followers receive the log entries in the same order and apply them, so they end up with identical data. Order matters: “add ₹100” then “set to ₹0” gives a different result in the other order.
  3. Reads from a follower can be stale

    leader = ["O1", "O2", "O3", "O4"]
    f2 = ["O1", "O2"]                   # F2 is two entries behind
    print("read from leader:", len(leader), "orders | read from F2:", len(f2), "orders")
    print("lag:", len(leader) - len(f2), "entries")
    read from leader: 4 orders | read from F2: 2 orders lag: 2 entries
    Followers are good for spreading read load, but they can be behind. A user who just changed their address might read the old one from a lagging follower.
  4. The leader fails: promote the best follower

    logs = {"F1": ["O1", "O2", "O3"], "F2": ["O1", "O2"]}
    acked = ["O1", "O2", "O3", "O4"]    # the leader had said OK to O4
    new_leader = max(logs, key=lambda f: len(logs[f]))
    print("promote:", new_leader, "| lost:", [o for o in acked if o not in logs[new_leader]])
    promote: F1 | lost: ['O4']
    The most up-to-date follower becomes leader. O4 had been acknowledged by the old leader but never reached a follower, so it is lost: the cost of asynchronous replication.
  5. Redirect clients and rejoin

    Clients learn the new leader’s address (through a DNS change, a proxy or a coordination service). When the old leader comes back, it must rejoin as a follower and discard writes the new leader never had.

    If the old leader came back still believing it was the leader, there would be two leaders: split brain (scenario 3).
  6. Choose the safety level per data

    Payments: synchronous or semi-synchronous replication within a region. Analytics replicas and cross-region copies: asynchronous. Kafka: acks=all with min.insync.replicas=2 for important topics.

    Replication is a dial between speed and safety. Choose it per dataset, based on how much loss (RPO) and downtime (RTO) the business can accept.
5 See it happen

Riya changes her address: which copy answers?

Step through the six frames. Left: Riya updating and re-checking her address. Right: the leader and followers, and which copy serves each request.

What Riya sees, and which copy answers 6 steps
What you see Delivery addressFlat 12, BanerSAVEDelivery addressAddress savedProfileRefreshing…ProfileAddress:Flat 4, Kothrud“But I just changed it!”ProfileRefreshing…ProfileAddress:Flat 12, Banercorrect every time myphatshala.in
Behind the screen LeaderoldFollower 1oldFollower 2oldThe write goes to the leader.LeaderNEWFollower 1oldFollower 2oldLeader saves it and says OK (async).LeaderNEWFollower 1NEWFollower 2oldFollower 1 has copied it; Follower 2 lags.LeaderNEWFollower 1NEWFollower 2oldHer read lands on lagging Follower 2: old data.LeaderNEWFollower 1NEWFollower 2oldFix: her reads go to the leader for a minute.LeaderNEWFollower 1NEWFollower 2NEWRead-your-writes: she always sees her change. myphatshala.in
6 Real-world use

Real-time scenarios: copies under failure

Three live scenarios: an automatic failover at 2 am, what Kafka’s acks setting really guarantees, and an advanced look at split brain and how fencing prevents it.

Real-time scenario 1

2:13 am: the leader dies

Three database nodes: A leads, B and C follow. At 2:13 am A's disk fails. Watch an automatic failover step by step, and where data can be lost.

Automatic failover 5 steps
Animated example Node AleaderNode BfollowerNode CfollowerNormal: A leads, B and C followHeartbeats every second. Writes go to A.Node A✗ downNode BfollowerNode Cfollower02:13:00 · A’s disk failsHeartbeats from A stop. Writes start failing.Node A✗ downNode Blog: 1,204Node Clog: 1,19902:13:10 · timeout reachedB and C compare logs: B is more up to date.B and C are a majority (2 of 3), so they may elect.Node A✗ downNode BNEW leaderNode Cfollows B02:13:20 · B promotedClients are redirected to B. Writes resume.Any writes A had not sent to B are lost (async).Node AfollowerNode BleaderNode CfollowerMorning · A repairedA rejoins as a follower and copies from B.It must never come back as a second leader. myphatshala.in
Real-time scenario 2

Kafka acks: when is a message really safe?

A payments service writes events to a Kafka topic with replication factor 3. The producer setting acks decides when the producer is told “done”. Watch what each setting means when a broker crashes.

acks = 0, 1, all 5 steps
Animated example Produceracks=0Leadermsg ✓Follower 1: —Follower 2: —acks=0: fire and forget. The producer doesn’t wait.Fastest; messages can vanish without anyone knowing.Produceracks=1Leadermsg ✓Follower 1: —Follower 2: —acks=1: OK once the leader has written it.Followers haven’t copied it yet.Produceracks=1Leadermsg ✓Follower 1: —Follower 2: —The leader crashes now. A follower becomes leaderwithout the message: acknowledged, then lost.Produceracks=allLeadermsg ✓Follower 1: ✓Follower 2: ✓acks=all: OK only when all in-sync replicas have it.Set min.insync.replicas=2 so at least 2 copies exist.Produceracks=allLeadermsg ✓Follower 1: ✓Follower 2: ✓Leader crashes: a follower already has the message.Nothing acknowledged is lost. Slightly slower writes. myphatshala.in
Real-time scenario 3 · advanced

Split brain: two leaders at once

The worst replication failure is not a crash but a network split, where the old leader keeps running and a new one is elected. Watch how majorities and fencing tokens keep only one leader in charge.

Split brain and fencing 5 steps
Animated example Node Aleader (epoch 1)Node BfollowerNode CfollowerA leads; B and C followThree nodes, one leader with epoch number 1.Node Aleader (epoch 1)Node BfollowerNode CfollowerNetwork partitionA is cut off from B and C, but A is still runningand some clients can still reach it.Node Astill thinks: leaderNode Bleader (epoch 2)Node CfollowerB and C (a majority) elect B, epoch 2Danger: A doesn’t know and still accepts writes.Two leaders = split brain. Data diverges.Node Asteps downNode Bleader (epoch 2)Node CfollowerDefence 1: majority quorumA alone is 1 of 3, not a majority: it must stopaccepting writes once it can’t reach a quorum.Node Aepoch 1 writes rejectedNode Bleader (epoch 2)Node CfollowerDefence 2: fencing tokenStorage remembers epoch 2 and rejects any writecarrying the older epoch 1. Only one leader wins. myphatshala.in

Replication at work

1. Managed databases with standby replicas

Cloud databases (such as Amazon RDS Multi-AZ or Azure SQL) keep a synchronous standby in another zone and fail over automatically, typically within a minute or two.

Primary (zone A)→Sync standby (zone B)→Auto failover

2. Read replicas for reports and dashboards

Reporting and analytics queries are sent to read replicas so they don’t slow down the primary that serves the app. Reports may lag by a few seconds, which is fine for them.

Primary: app writes→Async read replicas→Dashboards

3. Kafka for payments and orders

Fintech and e-commerce teams run critical topics with replication factor 3, min.insync.replicas=2 and acks=all, so a broker failure loses no acknowledged events.

Producer acks=all→3 replicas, ISR ≥ 2→No acknowledged loss

4. Disaster recovery across regions

Banks and large platforms keep an asynchronous copy in another region (for example Mumbai and Hyderabad) and rehearse switching over, accepting a few seconds of possible data loss in a regional disaster.

Region 1→Async cross-region copy→DR region
7 Run the code

A leader and two followers

Writes go to the leader's log. Each follower copies the log after its own delay. The program shows what each copy contains at a moment in time, which reads would be stale, and what a failover would lose. Then try the challenges: synchronous writes, choosing the new leader, quorums, Kafka acks and fencing tokens.

writes = [(0, "O1"), (2, "O2"), (4, "O3"), (6, "O4")]   # (time, order)
lag = {"F1": 1, "F2": 4}                                 # seconds behind the leader
now = 7

leader = [o for t, o in writes if t <= now]
followers = {f: [o for t, o in writes if t + d <= now] for f, d in lag.items()}

print("leader:", leader)
for f, data in followers.items():
    stale = len(leader) - len(data)
    print(f"{f}: {data}  ({stale} behind)")

# The leader crashes now: promote the follower with the most data
new_leader = max(followers, key=lambda f: len(followers[f]))
lost = [o for o in leader if o not in followers[new_leader]]
print("promote", new_leader, "| acknowledged but lost:", lost)
leader: ['O1', 'O2', 'O3', 'O4'] F1: ['O1', 'O2', 'O3', 'O4'] (0 behind) F2: ['O1', 'O2'] (2 behind) promote F1 | acknowledged but lost: []
  • lag = {"F1": 1, "F2": 4} # seconds behind the leaderAsynchronous followers apply changes a little later. Each has its own lag.
  • followers = {f: [o for t, o in writes if t + d <= now] for f, d in lag.items()}A follower has a write only if the write's time plus its lag has passed.
  • new_leader = max(followers, key=lambda f: len(followers[f]))On failover, the most up-to-date follower is promoted, losing as little as possible.

Run it on your PC: async vs semi-sync replication

This program simulates a leader and two followers on a clock. A client writes every two ticks; followers copy after a delay. It reads from a lagging follower, crashes the leader, promotes the best follower and lists acknowledged writes that were lost. Then it repeats with semi-synchronous replication and checks quorum settings. Save it as replication_sim.py and run it.

Replication, failover and quorums

"""A leader with two followers, simulated step by step on a clock.
Writes go to the leader's log; followers copy the log after a delay (asynchronous replication).
We read from a follower, crash the leader, fail over, and count what was lost.
Then we repeat with synchronous replication to one follower (semi-sync)."""


def run(mode, lag={"F1": 2, "F2": 5}, crash_at=12):
    leader_log = []
    follower_log = {"F1": [], "F2": []}
    pending = []                         # (arrival_time, follower, entry)
    acked = []
    for t in range(0, crash_at):
        if t % 2 == 0:                   # a client write every 2 ticks
            entry = f"order@{t}"
            leader_log.append(entry)
            for f, d in lag.items():
                pending.append((t + d, f, entry))
            if mode == "semi-sync":      # wait until F1 has it before saying OK
                follower_log["F1"].append(entry)
                pending = [p for p in pending if not (p[1] == "F1" and p[2] == entry)]
            acked.append(entry)
        for p in [p for p in pending if p[0] <= t]:
            follower_log[p[1]].append(p[2])
            pending.remove(p)
        if mode == "async" and t == 7:
            print(f"  t={t}: read from F2 sees {len(follower_log['F2'])} of {len(leader_log)} orders (replication lag)")
    # leader crashes; promote the follower with the longest log
    new_leader = max(follower_log, key=lambda f: len(follower_log[f]))
    lost = [e for e in acked if e not in follower_log[new_leader]]
    print(f"  leader crashed at t={crash_at}; promoted {new_leader} with {len(follower_log[new_leader])} of {len(acked)} acknowledged orders")
    print(f"  acknowledged but LOST: {lost if lost else 'none'}")


print("Asynchronous replication:")
run("async")
print("\nSemi-synchronous (leader waits for F1 before acknowledging):")
run("semi-sync")

# Quorum check for leaderless replication
print("\nQuorum reads/writes with N = 3 replicas:")
for w, r in [(1, 1), (2, 1), (2, 2), (3, 1)]:
    print(f"  W={w} R={r}: {'always reads the latest write' if r + w > 3 else 'may read stale data'}")

# In a terminal:  python replication_sim.py
Asynchronous replication: t=7: read from F2 sees 2 of 4 orders (replication lag) leader crashed at t=12; promoted F1 with 5 of 6 acknowledged orders acknowledged but LOST: ['order@10'] Semi-synchronous (leader waits for F1 before acknowledging): leader crashed at t=12; promoted F1 with 6 of 6 acknowledged orders acknowledged but LOST: none Quorum reads/writes with N = 3 replicas: W=1 R=1: may read stale data W=2 R=1: may read stale data W=2 R=2: always reads the latest write W=3 R=1: always reads the latest write

Recorded from a real run with Python 3.13; the simulation is deterministic, so you get the same output. Change lag or crash_at and see how many acknowledged writes are lost with async replication, and that semi-sync loses none as long as the follower it waited for survives.

8 Line by line

Followers applying the log, one line at a time

The leader's log has three entries. Follower F2 already has the first one. Watch it apply only the entries it is missing, in order.

Worked examples: real problems, solved and traced in memory

Four replication problems, from counting copies to choosing quorum settings. Each runs live and is traced.

Example 1BeginnerCapacity · copies

How much disk do copies need?

Problem statement

A Kafka cluster stores 20 TB of messages per week with replication factor 3, keeping 1 week. HDFS stores 50 TB with replication 3. How much raw disk does each need?

Input
Kafka 20 TB × 3, HDFS 50 TB × 3
Expected output
Kafka: 20 TB of data x 3 copies = 60 TB of disk
HDFS: 50 TB of data x 3 copies = 150 TB of disk
Total raw disk: 210 TB

Approach

  1. Raw disk = data × replication factor.
  2. Add both systems for the total.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 2IntermediateDatabase · lag monitoring

Which replicas are safe to read from?

Problem statement

Each read replica reports its lag in seconds. Reports can tolerate 30 s of lag; the checkout page tolerates 1 s. Print which replicas each workload may use.

Input
r1: 0.4 s, r2: 12 s, r3: 75 s
Expected output
checkout: ['r1']
reports : ['r1', 'r2']

Approach

  1. Store each replica's lag.
  2. For each workload, keep replicas with lag below its limit.
  3. If none qualifies, fall back to the primary.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 3IntermediateReliability · RPO

How much data can async replication lose?

Problem statement

Orders arrive at 3,000 per second. The async replica usually lags 0.5 s, but up to 4 s during peaks. How many orders could be lost if the primary died at a normal moment, and at a peak?

Input
3,000 orders/s, lag 0.5 s normal, 4 s peak
Expected output
normal: up to 1500 acknowledged orders could be lost
peak  : up to 12000 acknowledged orders could be lost
RPO target: 0 orders -> needs synchronous or semi-sync replication

Approach

  1. Orders at risk = arrival rate × lag.
  2. Compute for both lags.
  3. Compare with the business's acceptable loss (RPO).

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 4AdvancedDistributed DB · quorums

Choose quorum settings for each workload

Problem statement

With N = 3 replicas, list all (W, R) combinations, mark which are consistent (R + W > N), and pick the fastest consistent setting for a write-heavy workload (smallest W) and for a read-heavy one (smallest R).

Input
N = 3
Expected output
consistent settings: [(1, 3), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
write-heavy pick (W, R): (1, 3)
read-heavy pick  (W, R): (3, 1)

Approach

  1. Enumerate W and R from 1 to N.
  2. Keep combinations with R + W > N.
  3. Write-heavy: smallest W, then smallest R. Read-heavy: smallest R, then smallest W.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

9 Quiz and revision

Check yourself

Quick revision

Lesson 3.3 in one screen

  • Replication = copies on several nodes → availability, durability, read scaling, lower latency.
  • Architectures: single-leader (most common), multi-leader (multi-region), leaderless (quorums, R + W > N).
  • Sync (safe, slower) vs async (fast, can lose last writes) vs semi-sync (wait for one).
  • Replication lag → stale reads; fix with read-your-writes routing.
  • Failover: detect, promote most up-to-date follower, redirect, old leader rejoins as follower. RPO = data loss, RTO = downtime.
  • Kafka: RF 3, min.insync.replicas=2, acks=all, no unclean leader election.
  • Split brain prevented by majority quorums, fencing tokens/epochs and consensus (Raft, ZooKeeper). Replication ≠ backup.

Interview and viva questions

What is replication? Explain its types.

Replication keeps copies of the same data on multiple nodes for fault tolerance, availability, durability and read scalability. In single-leader replication one node accepts writes and streams changes to followers (PostgreSQL, MySQL, Kafka partitions). In multi-leader replication several nodes accept writes and exchange changes, useful across regions but requiring conflict resolution. In leaderless replication clients write to and read from several replicas and use quorums (R + W > N) for consistency, as in Cassandra and DynamoDB-style systems.

Compare synchronous and asynchronous replication.

In synchronous replication the leader acknowledges a write only after replicas confirm it, so no acknowledged data is lost if the leader fails, but write latency is higher and a slow or unavailable replica can block writes. In asynchronous replication the leader acknowledges immediately and replicas apply changes later, giving low latency but replication lag and possible loss of recent writes on failover. Semi-synchronous replication waits for at least one replica, balancing the two.

What is replication lag and what problems does it cause?

Replication lag is the delay between a write on the leader and its application on a follower. It causes stale reads, users not seeing their own updates (read-your-writes violations), data appearing to go backwards when reads hit different replicas (monotonic-read violations), and data loss on failover with asynchronous replication.

What is split brain and how is it prevented?

Split brain occurs when a network partition leads two nodes to act as leader simultaneously, both accepting writes so the data diverges. It is prevented by requiring a majority quorum to elect and keep a leader, by fencing tokens or epoch numbers that make storage reject writes from an old leader, and by using consensus algorithms such as Raft or Paxos (as in etcd, ZooKeeper and Kafka KRaft).

How does Kafka replication work?

Each partition has one leader broker and follower brokers that copy its log; followers that are fully caught up form the in-sync replica set (ISR). Producers choose acks=0 (no confirmation), acks=1 (leader only) or acks=all (all in-sync replicas). With replication factor 3, min.insync.replicas=2 and acks=all, an acknowledged message is stored on at least two brokers, and if the leader fails an in-sync follower takes over without losing it.

Practice problems

Replication exercises, from lag to quorums. The last two are business tasks.

P1Easy

Raw storage

Print the raw storage for 12 TB of data with replication factor 3.

Input
12 TB, RF 3
Expected output
36 TB
Show solution and explanation
print(12 * 3, "TB")
36 TB

How it works: Each copy needs the full space.

P2Easy

Replica lag

The leader is at log position 10,500 and a follower at 10,320. Print the lag in entries.

Input
10500, 10320
Expected output
180 entries behind
Show solution and explanation
print(10500 - 10320, "entries behind")
180 entries behind

How it works: Lag can be measured in log positions as well as seconds.

P3Easy

Majority size

Print the majority (quorum) size for clusters of 3, 4, 5 and 7 nodes.

Input
3, 4, 5, 7
Expected output
3 nodes -> majority 2
4 nodes -> majority 3
5 nodes -> majority 3
7 nodes -> majority 4
Show solution and explanation
for n in [3, 4, 5, 7]:
    print(n, "nodes -> majority", n // 2 + 1)
3 nodes -> majority 2 4 nodes -> majority 3 5 nodes -> majority 3 7 nodes -> majority 4

How it works: A 4-node cluster needs 3 for a majority, so it tolerates only 1 failure, like a 3-node cluster.

P4Medium

Failures tolerated

Print how many node failures a majority-quorum cluster tolerates for 3, 5 and 7 nodes.

Input
3, 5, 7
Expected output
3 nodes tolerate 1 failures
5 nodes tolerate 2 failures
7 nodes tolerate 3 failures
Show solution and explanation
for n in [3, 5, 7]:
    print(n, "nodes tolerate", (n - 1) // 2, "failures")
3 nodes tolerate 1 failures 5 nodes tolerate 2 failures 7 nodes tolerate 3 failures

How it works: A cluster keeps working while a majority is alive.

P5Medium

Promote the best follower

Given each follower's last log position, print the one to promote.

Input
F1: 880, F2: 905, F3: 870
Expected output
F2
Show solution and explanation
pos = {"F1": 880, "F2": 905, "F3": 870}
print(max(pos, key=pos.get))
F2

How it works: The most up-to-date follower loses the least data.

P6Advanced

Writes at risk

Orders arrive at 1,200/s. Async lag samples are given. Print the maximum number of orders at risk.

Input
lags [0.2, 0.4, 1.8, 0.3]
Expected output
2160 orders at risk in the worst case
Show solution and explanation
lags = [0.2, 0.4, 1.8, 0.3]
print(int(1200 * max(lags)), "orders at risk in the worst case")
2160 orders at risk in the worst case

How it works: Plan for the worst lag, not the average.

P7Advanced

Stale-read probability

A read goes to one of 3 replicas at random; at that moment 1 replica has the latest write. With R reads combined (taking the newest value), what is the chance of a stale result for R = 1, 2, 3?

Input
3 replicas, 1 up to date
Expected output
R=1: chance of stale result 67%
R=2: chance of stale result 33%
R=3: chance of stale result 0%
Show solution and explanation
from math import comb
N, fresh = 3, 1
for R in [1, 2, 3]:
    stale = comb(N - fresh, R) / comb(N, R)
    print(f"R={R}: chance of stale result {stale:.0%}")
R=1: chance of stale result 67% R=2: chance of stale result 33% R=3: chance of stale result 0%

How it works: Reading more replicas lowers the chance of missing the newest value; with R + W > N it becomes zero.

P8Business problem

Cost of a standby

A database server costs Rs 2.5 lakh a month. A synchronous standby doubles that. One hour of downtime costs the business Rs 40 lakh, and without a standby a failure causes 4 hours of downtime about once a year. Is the standby worth it?

Input
Rs 2.5 lakh/month, Rs 40 lakh/hour, 4 h/year
Expected output
standby: Rs 30.0 lakh/year vs expected downtime: Rs 160 lakh/year
worth it
Show solution and explanation
standby_per_year = 2.5 * 12
downtime_cost = 40 * 4
print(f"standby: Rs {standby_per_year} lakh/year vs expected downtime: Rs {downtime_cost} lakh/year")
print("worth it" if downtime_cost > standby_per_year else "not worth it")
standby: Rs 30.0 lakh/year vs expected downtime: Rs 160 lakh/year worth it

How it works: Availability decisions are business decisions: compare the cost of copies with the cost of being down.

P9Business problem

Cross-region RPO

A bank replicates asynchronously to a DR region with an average lag of 2 s and 800 transactions/s. The regulator expects RPO under 5 minutes. Print the transactions at risk and whether the RPO is met.

Input
2 s lag, 800/s, RPO 300 s
Expected output
transactions at risk: 1600
RPO met
Show solution and explanation
lag, rate, rpo = 2, 800, 300
print("transactions at risk:", lag * rate)
print("RPO met" if lag <= rpo else "RPO NOT met")
transactions at risk: 1600 RPO met

How it works: Async cross-region replication usually meets minute-level RPOs, while synchronous replication across distant regions would slow every transaction.

Real-world scenario questions (asked in company interviews)

Replication questions from real incidents and interviews. Decide your answer first, then open the model answer.

Database design · availabilityFresher

Make the orders database survive a server failure

The orders database runs on one server. Management wants it to survive a hardware failure with at most a minute of downtime and no lost orders.

The interviewer is checking: can you design basic replication with clear RPO/RTO?

Show a strong answer
  • Add a synchronous (or semi-synchronous) standby in another availability zone: RPO ≈ 0 for committed orders.
  • Automate failover with health checks and a managed service or a tool like Patroni, aiming for an RTO under a minute.
  • Connect apps through a stable endpoint (DNS or proxy) that moves to the new primary.
  • Add async read replicas for reports.
  • Keep point-in-time backups for mistakes and test restores regularly.

Avoid: saying “take nightly backups” as the answer to availability.

Consistency · user experience1–3 years

“I paid but the app says unpaid”

After adding read replicas, some customers see “payment pending” for a few seconds right after paying, and pay again.

The interviewer is checking: do you recognise replication lag and read-your-writes?

Show a strong answer

Reads go to asynchronous replicas that haven’t applied the payment yet. Fix: route a user’s reads to the primary for a short window after they write (or for critical screens like payment status), or read from a replica only if it has caught up to the user’s last write position. Make the payment API idempotent so a second tap doesn’t charge twice, and show “processing” instead of “unpaid” while confirming.

Avoid: removing replicas entirely, or adding a fixed sleep before reading.

Streaming · durability1–3 years

Messages lost during a broker restart

During a rolling restart of Kafka brokers, a few order events disappeared, although producers logged success.

The interviewer is checking: do you know how acks, ISR and unclean leader election interact?

Show a strong answer

Producers were probably using acks=1 (or the topic allowed unclean leader election), so a leader acknowledged messages and then lost leadership before followers copied them. Fix: replication factor 3, min.insync.replicas=2, producers with acks=all and idempotence enabled, and unclean.leader.election.enable=false. Restart brokers one at a time, waiting for under-replicated partitions to return to zero.

Avoid: adding retries in consumers, which can’t bring back a message that was never stored.

Fundamentals · interviewFresher

“Is replication the same as backup?”

Interviewers like this question because many candidates say yes.

The interviewer is checking: do you understand what each protects against?

Show a strong answer

No. Replication keeps live copies so the system survives machine, disk or zone failures with little downtime; every change, including mistakes and corruption, is copied within seconds. Backups are point-in-time copies kept separately so you can restore data after accidental deletes, bugs, ransomware or logical corruption. Production systems need both, and backups must be tested by actually restoring them.

Avoid: saying “we have three replicas, so we don’t need backups”.