AnyLearn
All lessons
Programmingadvanced

Replication and Partitioning

How do you scale a database beyond one machine while keeping it reliable? This lesson covers every major replication topology, the quorum math behind leaderless systems, and partitioning strategies from range keys to consistent hashing — including how to avoid hot partitions and handle rebalancing.

Not signed in — your progress and quiz score won't be saved.
Lesson progress1 / 9

Why replicate?

Replication serves two distinct goals that are often conflated:

  • Fault tolerance: if one node dies, another holds the data. Even a single replica raises durability from one hard drive's MTBF to the product of two independent failures.
  • Read throughput: serving reads from multiple replicas linearly scales read capacity. Writes still require coordination.

These goals pull in different directions. Maximizing fault tolerance (many replicas, synchronous) adds write latency. Maximizing read throughput (many replicas, async) risks serving stale data. Every replication strategy is a trade-off between these two axes. Before choosing a topology, decide which failure scenarios you're designing for and what staleness the application can tolerate.

Full lesson text

All 9 steps on one page — for reading, reference, and search.

Show

1. Why replicate?

Replication serves two distinct goals that are often conflated:

  • Fault tolerance: if one node dies, another holds the data. Even a single replica raises durability from one hard drive's MTBF to the product of two independent failures.
  • Read throughput: serving reads from multiple replicas linearly scales read capacity. Writes still require coordination.

These goals pull in different directions. Maximizing fault tolerance (many replicas, synchronous) adds write latency. Maximizing read throughput (many replicas, async) risks serving stale data. Every replication strategy is a trade-off between these two axes. Before choosing a topology, decide which failure scenarios you're designing for and what staleness the application can tolerate.

2. Single-leader (leader/follower) replication

The dominant approach: one node is the leader (primary), all others are followers (replicas). Writes go to the leader; the leader ships a replication stream (WAL, binlog, or logical log) to followers.

Client → Leader → [replication stream] → Follower 1
                                        → Follower 2

Synchronous replication: the leader waits for at least one follower to confirm before acknowledging the write. Durability guarantee: survives leader crash. Cost: write latency is bound to the slowest sync follower.

Asynchronous replication: leader acknowledges immediately, ships to followers in the background. Throughput is high; a leader crash before replication completes loses committed writes.

Semi-sync (MySQL default): exactly one follower is synchronous, the rest are async. Balances durability and latency. Most production MySQL and PostgreSQL streaming setups use this.

3. Multi-leader replication

Multi-leader (active-active) allows writes at multiple nodes — typically one per datacenter — and replicates asynchronously between them.

Advantages:

  • Writes go to a local datacenter: low latency for geographically distributed users.
  • Survives a full datacenter outage with no failover needed.

The fundamental problem: write conflicts. If two leaders accept concurrent writes to the same key, there's no total order. You must have a conflict resolution policy:

  • Last-write-wins (LWW): use timestamps. Lossy when clocks skew.
  • Application-level merge: expose the conflict to the application (CouchDB, Riak). Correct but complex.
  • CRDT types: limit writes to CRDT-compatible operations (counters, sets, maps). Conflict-free by construction.

For most applications, the complexity of multi-leader conflict resolution outweighs its benefits. Use it only when cross-datacenter write latency is an explicit SLA requirement.

4. Leaderless replication and quorums

In leaderless systems (Dynamo-style: Cassandra, Riak, DynamoDB), any node accepts reads and writes. Consistency is achieved via quorum rules.

Given NN replicas, write to WW, read from RR:

W+R>N    quorum overlap1W + R > N \implies \text{quorum overlap} \ge 1

Common configurations for N=3N=3:

ConfigWWRRDurabilityRead latency
Strong quorum22HighMedium
Write-heavy31HighestLow
Read-heavy13LowHigh

Caution: W+R>NW + R > N does not guarantee linearizability. If a write and a read execute concurrently, the quorum may not overlap in the right nodes. Cassandra's QUORUM gives strong eventual consistency, not linearizability. For linearizability you need SERIAL consistency (per-key Paxos).

5. Partitioning strategies: range vs. hash

Partitioning (sharding) splits data across nodes so each node holds a subset. Two main strategies:

Range partitioning: assign contiguous key ranges to each partition (e.g., [A–F], [G–M], [N–Z]).

  • Pro: range scans are efficient — all keys in a range are co-located.
  • Con: hot partitions if writes cluster in a range (e.g., all new records have today's timestamp prefix).

Hash partitioning: partition = hash(key) % num_partitions.

  • Pro: distributes load uniformly across partitions.
  • Con: range scans require querying all partitions. Cassandra uses this; range queries are scatter-gather.
# Hash partitioning assignment
def get_partition(key: str, num_partitions: int) -> int:
    return int(hashlib.md5(key.encode()).hexdigest(), 16) % num_partitions

A common hybrid: hash the first part of a compound key, range-sort the second. Cassandra's partition key + clustering key does exactly this: hash gets you to a node, the clustering key gives you sorted access within the partition.

6. Consistent hashing

Naive hash partitioning has a fatal flaw: adding or removing a node requires rehashing and moving N/M\approx N/M of all keys (where NN = keys, MM = nodes). Consistent hashing solves this.

The algorithm:

  1. Map both nodes and keys onto a conceptual ring of hashes (typically [0,232)[0, 2^{32})).
  2. Each key belongs to the first node clockwise from its hash position.
  3. Adding a node: only keys between the new node and its predecessor migrate — roughly 1/M1/M of total keys.
  4. Removing a node: its keys move to its successor — again roughly 1/M1/M.

Virtual nodes (vnodes): assigning each physical node multiple ring positions (e.g., 256 tokens in Cassandra) improves load balance and makes the migration on node changes even smaller. Without vnodes, unlucky ring positions can create hot spots.

Consistent hashing is used in Cassandra, Dynamo, Amazon S3, and most CDN key distribution systems.

7. Rebalancing and hot partitions

Even with perfect initial distribution, two operational hazards emerge over time:

Hot partitions: a single partition receives disproportionate traffic. Common causes:

  • Celebrity/viral data (all reads go to one key).
  • Monotonically increasing keys (all writes go to the last partition).
  • Poor partition key choice.

Fixes: add a random prefix to hot keys (shard the hot partition), use a secondary fan-out write path, or add a caching layer in front.

Rebalancing: when you add nodes, data must move. Strategies:

  • Fixed number of partitions (Elasticsearch): pre-shard into many more partitions than nodes (e.g., 1000 shards, 10 nodes); add a node → reassign whole shards. Simple, but shard size must be tuned upfront.
  • Dynamic partitioning (HBase, RethinkDB): split a partition when it exceeds a size threshold; merge when it shrinks. Adapts automatically but adds metadata complexity.
  • Proportional to nodes (Cassandra vnodes): fixed partitions per node; adding a node steals evenly from existing nodes.

Monitor partition size and request-rate skew in production — imbalance compounds quickly under write pressure.

8. Replication topology comparison

Three topologies and their write paths:

flowchart LR
  A["Client"]
  B["Leader"]
  C["Follower 1"]
  D["Follower 2"]
  E["Leader DC-A"]
  F["Leader DC-B"]
  G["Any node"]
  H["Replica quorum"]
  A --> B
  B --> C
  B --> D
  E --> F
  F --> E
  A --> G
  G --> H

9. Putting it together: choosing a replication and partitioning strategy

A decision framework:

RequirementRecommendation
Strong consistency, OLTPSingle-leader + sync replication + range partitioning
High write throughput, eventual OKLeaderless (Cassandra) + hash partitioning + vnodes
Multi-region low-latency writesMulti-leader + CRDT/LWW conflict resolution
Large range scans (time-series)Single-leader + range partitioning + random prefix for hot keys
Elastic scaling, cloud-nativeFixed sharding (Elasticsearch) or proportional vnodes

The biggest mistakes in practice: (1) using eventual consistency for data that requires strong consistency, (2) choosing a partition key that creates hot spots at launch, (3) under-provisioning shard count so rebalancing becomes painful at scale. Test with production-like key distributions before launch.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. In a Cassandra cluster with N=3, W=2, R=2, a write is acknowledged by 2 nodes. A read immediately after contacts 2 nodes, one of which is the slow replica that hasn't applied the write yet. What does the client read?
    • Always the latest write, because W+R > N guarantees it.
    • Possibly a stale value, because quorum overlap does not guarantee linearizability under concurrency.
    • An error, because the quorum is inconsistent.
    • The latest write, because Cassandra's coordinator performs a read-repair before responding.
  2. You add a new node to a cluster using consistent hashing. Approximately what fraction of keys must migrate?
    • All keys must be rehashed.
    • Half the keys.
    • $1/M$ of keys, where M is the new total number of nodes.
    • No keys migrate; only new writes go to the new node.
  3. A social media app partitions user posts by user_id using hash partitioning. A celebrity with 50M followers posts and all reads hit the same partition. What is this problem called and what is a standard fix?
    • Split-brain; fix by using multi-leader replication.
    • Hot partition; fix by adding a random prefix (e.g., 0-9) to the partition key to spread the load.
    • Clock skew; fix by using vector clocks on the partition.
    • Quorum imbalance; fix by increasing the replication factor.
  4. MySQL semi-synchronous replication guarantees that a committed transaction is on at least two nodes. What is the trade-off compared to fully asynchronous replication?
    • Higher write latency because the leader waits for one synchronous follower to acknowledge before responding.
    • Lower read throughput because followers cannot serve reads while syncing.
    • Linearizability of all reads across replicas.
    • Automatic failover without any data loss.
  5. You use range partitioning with partition keys that are event timestamps (e.g., 2024-05-23T...). What operational problem will you hit as the system grows?
    • Range scans will become impossible because timestamps are not sortable.
    • All new writes will go to the last (most recent) partition, creating a hot write partition.
    • Consistent hashing will fail to distribute keys evenly.
    • Followers will fall behind because timestamp-ordered writes cannot be replicated.

Related lessons