Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 8 – Replication

Leaderless replication and quorums: N, R and W

How Dynamo-style stores read and write with quorums: choosing N, R and W, sloppy quorums, hinted handoff and repair, and what R + W > N leaves out.

  • Advanced
  • 35 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free intro, Pro: 8 of 35 minutes free
Free: Reads and writes that overlap. With a pass: the other 8 sections and 3 interview answers, about 27 minutes.

What you will learn

  • Explain why R + W > N makes a read meet the latest acknowledged write
  • Choose N, R and W for a target consistency, availability and latency
  • Recognise what quorums do not guarantee, and what blocking read repair restores
  • Explain sloppy quorums, hinted handoff, read repair and anti-entropy, and what each costs
  • Distinguish the leaderless design of the Dynamo paper from the way Amazon DynamoDB replicates

Before you start

What you’ll learn · Before you start

What you will learn

  • Explain why R + W > N makes a read meet the latest acknowledged write
  • Choose N, R and W for a target consistency, availability and latency
  • Recognise what quorums do not guarantee, and what blocking read repair restores
  • Explain sloppy quorums, hinted handoff, read repair and anti-entropy, and what each costs
  • Distinguish the leaderless design of the Dynamo paper from the way Amazon DynamoDB replicates

Before you start

On this page

A key lives on three replicas, a write waits for two of them to confirm, and a read asks two. Because 2 + 2 is more than 3, the replicas a read asks always include one that the last acknowledged write reached. Leaderless replication drops the leader altogether: a client, or a coordinator acting for it, sends every write to all N replicas of a key and counts it as done once W of them confirm, and a read waits for R answers and keeps the newest version it sees. These quorums are what make the copies agree: if R + W > N, every set of replicas a read asks shares at least one replica with every set a write reached. Stores in the style of Amazon’s Dynamo, such as Cassandra, work this way, and they keep answering when a replica is slow or down, because no single server has to reply.

Reads and writes that overlap

The Dynamo paper defines R and W as the minimum numbers of replicas that must take part in a successful read and a successful write, notes that R + W > N gives a quorum-like system, and observes that the latency of each request is set by the slowest of the R or W replicas it waits for; the common configuration there was N = 3, R = 2, W = 2 (Dynamo). Cassandra states the same rule as consistency levels, where QUORUM means a majority, n/2 + 1, of the replicas, and levels chosen with W + R greater than the replication factor make every acknowledged write visible to later reads (Cassandra). In the diagram, look for the replica that the write and the read share:

A write goes to three replicas and succeeds after two; a read asks two replicas, one of which has the new value, and keeps it.Writer: put(cart, v2)sent to all 3 replicas,done after W = 2 repliesReplica 1has v2Replica 2has v2Replica 3still has v1Reader: get(cart)asks R = 2 replicas,keeps the newest: v2acknowledgedacknowledgedlatev2v1

N = 3, W = 2, R = 2

Text description of the diagram

At the top, a writer stores version v2 of a cart. It sends the write to all three replicas and counts it as done once two of them, W = 2, have acknowledged it.

Replicas 1 and 2 acknowledged the write and hold v2. The write reaches replica 3 late, so it still holds the older version v1.

At the bottom, a reader asks two replicas, R = 2: replica 2 answers v2 and replica 3 answers v1. Because R + W = 4 is more than N = 3, any two replicas the reader asks include at least one that holds the newest acknowledged write, and the reader keeps the newer version, v2.

Step through the diagram’s write and read:

Interactive · step by step A quorum write, then a quorum read Step through one write that waits for two of three replicas, then one read that asks two. Watch which replica the two sets share.
A quorum write, then a quorum read, step 5 of 5. Showing Writer, Replica 1 (has v2), Replica 2 (has v2), Replica 3, Reader (keeps v2). In focus: Reader.Writerput(cart, v2)Replica 1has v2Replica 2has v2Replica 3has v1Readerkeeps v2

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. The write goes to all three. The writer sends v2 of the cart to all three replicas of the key, N = 3, and will count it as done once two of them, W = 2, confirm.
  2. Two replicas confirm. Replicas 1 and 2 store v2 and confirm. That is W = 2, so the write is acknowledged, while replica 3 has not received it yet.
  3. One replica is late. The write is still on its way to replica 3. Nothing waits for it, and for now replica 3 holds v1.
  4. The read asks two. A reader asks two replicas, R = 2, here replicas 2 and 3. They answer v2 and v1.
  5. The newest version wins. The reader keeps the newest version it saw, v2. Any two replicas it could have asked include replica 1 or 2, because R + W = 4 is more than N = 3.

The quorum explorer below tries nine choices. A write reaches each replica after a random delay and is acknowledged once W replicas hold it; a read made right then asks R random replicas.

A quorum explorer for N, R and W JavaScript · explorer/quorum_explorer.mjs
// A quorum explorer: for each choice of N, R and W, does every read meet every write, how many replicas may be
// down, and how often does a read right after an acknowledged write miss it? The write reaches each replica after
// a random delay of 0 to 40 ms and is acknowledged once W replicas hold it; the read asks R random replicas at
// that moment and takes the newest version it sees. Seeded, so every run prints the same; edit CHOICES and run it.
const CHOICES = [
  [3, 1, 1], [3, 1, 2], [3, 2, 1], [3, 2, 2], [3, 1, 3], [3, 3, 1],
  [5, 2, 2], [5, 3, 3], [5, 1, 5],
];
const TRIALS = 20000;

function mulberry32(seed) {
  return () => {
    seed = (seed + 0x6d2b79f5) | 0;
    let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

function shuffled(items, random) {
  const out = [...items];
  for (let i = out.length - 1; i > 0; i--) {
    const j = Math.floor(random() * (i + 1));
    [out[i], out[j]] = [out[j], out[i]];
  }
  return out;
}

console.log('"down": how many replicas may be down while writes,');
console.log('or reads, still succeed.');
console.log(' N  R  W  overlap  writes   reads    stale reads');
for (const [n, r, w] of CHOICES) {
  const random = mulberry32(7);
  let stale = 0;
  for (let i = 0; i < TRIALS; i++) {
    const arrival = Array.from({ length: n }, () => 40 * random()); // ms after the write is sent
    const acked = [...arrival].sort((a, b) => a - b)[w - 1]; // the moment the W-th replica holds it
    const asked = shuffled([...arrival.keys()], random).slice(0, r);
    if (asked.every((k) => arrival[k] > acked)) stale++;
  }
  const overlap = r + w > n ? 'yes' : 'no';
  console.log(
    `${String(n).padStart(2)} ${String(r).padStart(2)} ${String(w).padStart(2)}  ${overlap.padEnd(7)}  ` +
      `${n - w} down   ${n - r} down   ${((100 * stale) / TRIALS).toFixed(1).padStart(5)} %`,
  );
}

Output

"down": how many replicas may be down while writes,
or reads, still succeed.
 N  R  W  overlap  writes   reads    stale reads
 3  1  1  no       2 down   2 down    66.9 %
 3  1  2  no       1 down   2 down    33.8 %
 3  2  1  no       2 down   1 down    34.1 %
 3  2  2  yes      1 down   1 down     0.0 %
 3  1  3  yes      0 down   2 down     0.0 %
 3  3  1  yes      2 down   0 down     0.0 %
 5  2  2  no       3 down   3 down    30.2 %
 5  3  3  yes      2 down   2 down     0.0 %
 5  1  5  yes      0 down   4 down     0.0 %

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node quorum_explorer.mjs

Every row with R + W > N found the write every time, and every row without that overlap often missed it: two reads in three with R = W = 1. The other columns are the cost of each choice, since W = N stops writes when any replica is down and R = N does the same to reads. Strict quorums are the easy part. The interesting behaviour comes from what leaderless replication does when replicas fail:

  • sloppy quorum: A quorum that, when a key's own replicas are unreachable, counts confirmations from the next healthy nodes instead, so the write still succeeds.: when a key’s own replicas are unreachable, the write goes to the next healthy nodes, so it still succeeds.
  • hinted handoff: A substitute node keeps a write meant for an unreachable replica, with a hint naming that replica, and hands the write over once the replica is back.: a substitute keeps such a write with a note of its rightful replica and hands it over later.
  • read repair: A read that finds some of the replicas it asked holding an older version writes the newest version it saw back to them.: a read that sees stale replicas writes the newest version back to them.
  • anti-entropy: Replicas compare their data in the background, using trees of hashes, and copy whatever differs, so that they converge without waiting for reads.: replicas compare hash trees of their data in the background and copy whatever differs.

Overlapping quorums are still not linearisability: concurrent writes, failed writes and sloppy quorums all let reads see results that a single copy never would.

Checkpoint

Check: Why R + W > N makes sets overlap

  1. Question 1 of 2 A key has N = 3 replicas and writes wait for W = 2. What is the smallest R for which every read set overlaps every write set?

    Type a number.

    A hint

    The sets overlap when R + W is more than N.

    Show the answer: Question 1 of 2

    Answer: 2 replicas

    R + 2 > 3 needs R = 2. With R = 1 a read can ask the one replica the write has not reached yet, which is why the explorer's R = 1, W = 2 row missed the write in a third of its reads.

  2. Question 2 of 2 In the quorum explorer, with N = 3, R = 1 and W = 1, what share of the reads made right after an acknowledged write missed it?

    Type a number.

    A hint

    Read the first row of the explorer's table.

    Show the answer: Question 2 of 2

    Answer: 66.9 % (anything from 66.6 to 67.2 counts)

    66.9 %, about two reads in three: the write was acknowledged by one replica, and a read that asks one random replica finds the other two still holding the old version. Every row with R + W > N missed nothing.

Choosing N, R and W, with numbers Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • What a quorum does not promise
    • Two surprises of a strict quorum, reproduced
  • Sloppy quorums and hinted handoff
  • Read repair and anti-entropy with Merkle trees
    • Finding the keys that differ with a Merkle tree, counted
  • DynamoDB is not Dynamo
  • Practise: combine a quorum read and plan its repair
    • Combine a quorum read and plan its read repair
  • Interview questions
    • A shopping-cart service keeps each cart on N = 3 replicas of a leaderless store. Carts must keep accepting writes when one replica is down, and users must see their own change on the next page. Choose R and W, and say what can still go wrong.
    • Your store uses N = 3, R = 2 and W = 2, yet a support ticket shows a customer reading a new value and then an older one a moment later. A colleague says that is impossible because R + W > N. Who is right, and how could it happen?
    • During a network partition your leaderless store can either accept writes for a key on substitute nodes, a sloppy quorum, or reject them. Which would you choose for shopping carts, and which for an inventory counter, and what must be in place either way?
  • Key takeaways

4 diagrams · 3 runnable examples (Python) · 1 exercise with sample tests · 3 interview answers · about 40 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Design a unique ID generator

Terms in this lesson

anti-entropy
Replicas compare their data in the background, using trees of hashes, and copy whatever differs, so that they converge without waiting for reads.
hinted handoff
A substitute node keeps a write meant for an unreachable replica, with a hint naming that replica, and hands the write over once the replica is back.
Merkle tree
A tree of hashes: each leaf hashes one part of the data and each parent hashes its children, so two copies whose hashes match at a node hold the same data below it.
quorum (N, R and W)
The number of a key's N replicas that must take part: W for a write to succeed, R for a read. When R + W is more than N, every set of replicas a read asks shares at least one replica with every set a write reached.
read repair
A read that finds some of the replicas it asked holding an older version writes the newest version it saw back to them.
sloppy quorum
A quorum that, when a key's own replicas are unreachable, counts confirmations from the next healthy nodes instead, so the write still succeeds.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.