Replication — leader, multi-leader, leaderless
Three topologies for the same problem: keep multiple copies in sync.
Replication is the foundation of every reliable database. You store the same data on multiple machines so that when one dies — and machines do die — you can keep serving reads and writes from another. But how to keep replicas in sync is one of the oldest and hardest problems in distributed systems. Three families have emerged: single-leader (the standard), multi-leader (for multi-region writes), and leaderless (Dynamo-style). Each makes a different consistency-vs-availability trade-off.
Replication answers three business needs at once: availability (if one node dies, keep serving), scale reads (multiple replicas serve read traffic), and geographic proximity (put a replica near the user). But every replication topology forces a trade-off — the CAP triangle in action. You cannot have strong consistency, instant availability, and multi-region writes simultaneously.
The three topologies
The distinction is who accepts writes. Single-leader: one node accepts all writes. Multi-leader: multiple nodes accept writes; they synchronize with each other. Leaderless: any replica accepts writes; readers reconcile inconsistency at read time.
The three topologies visualized
Single-leader replication — the default
Also called master-slave (deprecated terminology) or primary-replica. One node is the leader; all writes go there. Followers replicate from the leader — either synchronously (leader waits for follower ACK before returning to client — strong durability, higher latency) or asynchronously (leader ACKs client immediately, follower catches up eventually — lower latency, risk of data loss on leader failure).
The trade-offs of async vs sync replication: Async is the default (Postgres streaming replication, MySQL binlog) because it doesn't hurt write latency. Cost: if the leader dies before replicating, that write is lost. Semi-synchronous (MySQL, Postgres) requires at least one replica to ACK — a compromise. Fully synchronous is rare because one slow replica stalls all writes.
Failover — the hard part
When the leader dies, you need to promote a follower. This sounds simple until you handle:
- Split brain: if the network partitions and both sides elect a new leader, you get two leaders accepting conflicting writes. Requires consensus (Raft, Paxos) to prevent.
- Lost writes: with async replication, some writes on the old leader never made it to the new leader. Data loss is the norm.
- Timeout tuning: too aggressive (false failovers on GC pauses) or too slow (users wait for minutes).
- Redirect clients: apps need to know where the new leader is. DNS, service discovery, or client-side libraries handle this.
Multi-leader replication — for multi-region writes
Single-leader gives you strong consistency but only one region can accept writes. If your users are global, this means every write from Tokyo travels to (say) the US East region — 200ms of round-trip. Multi-leader lets every region accept its own writes, then replicates asynchronously to peers.
The catch: conflicts. Alice in Tokyo updates her profile to "pronouns: they/them." At the same instant, Alice in San Francisco (via her phone on a plane over the Pacific) updates "pronouns: she/her." Both regions accept the write. Which wins? Conflict resolution options:
- Last-write-wins (LWW) — pick the highest timestamp. Simple, arbitrary, sometimes loses data.
- Application-level — surface the conflict to the app (like Git merge conflicts). Riak siblings pattern.
- CRDTs — data structures that merge without conflict (G-Counter, LWW-Set, etc.). Perfect for counters, sets, some documents.
Leaderless replication — the Dynamo model
Amazon Dynamo (2007) took a radical position: no leader at all. Any replica accepts writes. Any replica serves reads. Consistency is achieved via quorums: write to W of N replicas, read from R of N, and require R + W > N.
Cassandra, DynamoDB, Riak all use this. The nice property: every node is equal. No leader election, no failover — if a node is down, the others just pick up the slack. Cost: reads may see stale data unless you hit the read quorum, and clock skew across replicas can produce weird outcomes.
Comparison — which one to pick
| Dimension | Single-leader | Multi-leader | Leaderless |
|---|---|---|---|
| Consistency | Strong (at leader) | Eventual (conflicts possible) | Tunable (via R+W) |
| Multi-region writes | ❌ (leader is one region) | ✅ Native | ✅ Native |
| Read scaling | ✅ Follower reads (may be stale) | ✅ Every leader serves reads | ✅ Any replica |
| Conflicts | Impossible | Real problem — need resolution | Rare — quorums prevent most |
| Failover | Complex — split-brain risk | Not needed | Not needed |
| Best fit | Single-region OLTP, transactional apps | Multi-region users, offline-first apps | High-write throughput, PB-scale |
| Real users | Postgres, MySQL, MongoDB, InnoDB, Cockroach per-range | DynamoDB Global Tables, MySQL Group Repl, BDR | Cassandra, DynamoDB, Riak |
Applied in real systems
Postgres — streaming replication (single-leader)
Async streaming replication is default. One primary + N replicas via WAL streaming. Failover via Patroni/repmgr + Consul/etcd. Semi-sync available via synchronous_commit=on.
MySQL — binlog replication + Group Replication
Traditional single-leader via binlog. Group Replication (5.7+) provides multi-primary via Paxos. Percona XtraDB Cluster uses Galera for synchronous multi-primary.
MongoDB — replica sets (single-leader with auto-failover)
Replica sets have 1 primary + N secondaries. Async oplog replication. Raft-based primary election. Read preferences (primary, secondary, nearest) let you route reads.
Cassandra — leaderless with tunable quorum
N replicas per token range. Coordinator writes to all, waits for W ACKs. Reads request from R replicas. NetworkTopologyStrategy for rack awareness. LOCAL_QUORUM standard for multi-region.
DynamoDB — hidden leaderless
DynamoDB is Dynamo the paper, evolved. 3 copies (one per AZ). Writes go to at least 2 of 3. Global tables (multi-region) do cross-region eventual consistency via streams.
CockroachDB — Raft per range
Every 512 MB range has its own Raft group of 3-5 replicas. Writes = Raft consensus. Reads at leaseholder. Automatic rebalancing across nodes and DCs.
DynamoDB Global Tables — multi-leader cross-region
Every region is a leader, replicating async cross-region via DynamoDB Streams. LWW conflict resolution. Sub-second replication typical.
Riak — siblings for multi-leader conflicts
Riak was the purest Dynamo clone (Basho). When multi-master writes conflict, Riak stores both as siblings and the app resolves at read time. Vector clocks for causality.
Key takeaways
- Three topologies: single-leader (default, strong consistency), multi-leader (multi-region writes, conflict resolution needed), leaderless (Dynamo-style, quorums).
- Async vs sync replication is the fundamental latency-vs-durability trade-off. Async is faster but risks data loss on failover.
- Failover is hard: split-brain, lost writes, timeout tuning. Consensus (Raft) is the only clean solution for automatic failover.
- Multi-leader = conflict resolution. LWW, app-level, CRDTs. Every solution loses some data or surfaces the mess to the app.
- Leaderless (Dynamo): quorum-based. Any node takes writes, any node serves reads. R+W>N gives strong reads. Cassandra + DynamoDB + Riak.
- Every serious database has one of these three. Learn to identify which and its exact consistency guarantees.
References
- DeCandia et al. (2007) — Dynamo.
- Kleppmann (2017) — DDIA, Chapter 5.
- Postgres, MySQL, MongoDB, Cassandra docs on replication.
Practice what you just read
Every foundation concept has a companion quiz to close the loop.