user@techdebt:~/blog$_
$ cd ..

The Replica

W(2) + R(2) = 4 > N(3)
mode:
$ replication inspector
click Step or Play to inspect replication state
$ simulation.log

the problem

Your database lives on one server. That server has a disk, and disks fail. When it goes down, your entire application goes with it. Even if you have backups, restoring takes time: minutes to hours of downtime.

The fix sounds simple: keep copies. But the moment you have two copies of the same data, you have a new problem: keeping them in sync. Every write has to reach all copies, and that takes time. During that window, different copies have different data. Welcome to replication.

leader-follower

The most common setup: one node is the leader (also called primary or master). All writes go to the leader. The leader sends a stream of changes to followers (replicas, secondaries). Reads can go to any node.

# write path — always through the leader
def write(key, value):
    leader.apply(key, value)
    for follower in followers:
        follower.replicate(key, value)  # async

# read path — any node
def read(key):
    return any_node.get(key)

This is how PostgreSQL streaming replication, MySQL replication, and MongoDB replica sets work.

replication lag

If replication is asynchronous (and it almost always is), followers lag behind. A client that writes to the leader and immediately reads from a follower might get stale data.

This gap between what the leader knows and what followers know is replication lag. Under normal load it’s milliseconds. Under heavy write traffic or network issues, it can be seconds or more.

The sim above demonstrates this: after a write, followers don’t update instantly. Reading from a lagging follower returns the old value.

failover

When the leader dies, a follower must be promoted. This is failover:

  1. Detect the leader is down (usually via heartbeat timeout)
  2. Choose a follower, typically the one with the least lag
  3. Promote it to leader
  4. Redirect all writes to the new leader

The dangerous part: if the old leader had writes that didn’t replicate before it died, those writes are lost. The new leader has a slightly older view of the data. In practice, systems like PostgreSQL use synchronous replication for at least one follower to prevent this.

multi-leader

What if your users are in New York and London? With a single leader in New York, London writes cross the Atlantic, adding 80ms+ of latency to every write.

Multi-leader replication puts a leader in each datacenter. Local writes are fast. Leaders sync with each other asynchronously.

The problem: two leaders can accept conflicting writes to the same key. Client A writes user:1='Alice' in New York while Client B writes user:1='Bob' in London. When the leaders sync, they disagree.

Conflict resolution strategies:

  • Last-Write-Wins (LWW): highest timestamp wins. Simple but lossy; one write is silently discarded.
  • Merge: combine values (works for counters, sets; doesn’t work for arbitrary data).
  • Application-level: surface the conflict to the user (like Google Docs showing concurrent edits).

leaderless replication

Instead of routing writes through a leader, send them to all replicas. A write succeeds when W out of N nodes acknowledge it. A read queries R nodes and takes the latest version.

The consistency formula: W + R > N guarantees you’ll always read the latest write. At least one of the R nodes you read from must have the latest W-acknowledged write.

N = 3 replicas
W = 2 (write to 2 nodes)
R = 2 (read from 2 nodes)

W + R = 4 > 3 = N  ✓ guaranteed overlap

Break the formula (W=1, R=1) and you can read stale data: the one node you read from might not be the one that got the write.

This is how Cassandra and DynamoDB’s consistency model works. You tune W and R per query to trade consistency for latency.

where it shows up

  • PostgreSQL: streaming replication with synchronous/async modes. pg_basebackup for initial follower setup.
  • MySQL: binlog-based replication. Group Replication adds multi-leader with conflict detection.
  • MongoDB: replica sets with automatic failover. Write concern and read preference control consistency.
  • Cassandra: leaderless with tunable consistency. QUORUM reads/writes give you W+R>N automatically.
  • Amazon DynamoDB: leaderless under the hood. ConsistentRead=true forces reads from the leader partition.