Skip to main content

Quorums: N, R, W

Introduction

Here are two commands, run against the same row, on the same database, seconds apart. I ran them on a real three-node Cassandra cluster while writing this lesson.

CONSISTENCY ONE;
SELECT items FROM shop.cart WHERE id = 'u1';

   u1 | v1-ORIGINAL        <-- the OLD value. And the read succeeded, cheerfully.


CONSISTENCY QUORUM;
SELECT items FROM shop.cart WHERE id = 'u1';

   Unavailable exception: "Cannot achieve consistency level QUORUM"
   info = {'required_replicas': 2, 'alive_replicas': 1}

The cart had been updated. The write returned success — the customer was told their item was added. And the first read handed back the previous contents of the cart, with no error, no warning, and no hint that anything was wrong.

The second read refused to answer at all.

Neither of those is a bug. Both of them are the database doing exactly what I asked — and the difference between them is a single number I chose. One of those numbers bought me availability and sold my correctness. The other did the reverse, and was honest about it.

Replication Topologies left you with an obvious, nagging question about leaderless systems: if a write goes to some nodes, and a read asks some nodes, how on earth do I guarantee I see my own write? And Sync vs Async Replication & Failover left you with a different problem that turns out to have the same answer: synchronous replication made your leader depend on one specific follower — kill that follower and the leader stops committing. I told you the fix was to require an acknowledgment from any one of several rather than one named machine.

Both of those are the same idea, and it's the most elegant piece of arithmetic in distributed systems. It fits on one line:

R + W > N

In this lesson: what those three letters mean; a two-sentence proof of why the rule works (it's the pigeonhole principle, and once you see it you can't unsee it); how the very same three numbers also decide how many machines may die and how slow your queries are; the four settings of the dial and what each one is really buying; and then the honest part — why R + W > N is not the strong consistency guarantee that almost everyone thinks it is.

Scope: how a node that missed a write gets caught up — read repair, hinted handoff — is Read Repair & Hinted Handoff. (I deliberately switched both of those OFF for the experiment above, because I wanted you to see the gap rather than watch Cassandra quietly paper over it.) The proper vocabulary for exactly how stale a read is allowed to be is The Consistency Spectrum. And what to do when two writes race is Version Conflicts.

The quorum overlap rule drawn as two rings of the same three replicas, side by side. On the left, in red, the setting W = 1 and R = 1: one plus one is two, which is NOT greater than three. Node n1 is filled green because it got the write; node n3 is circled in a dashed blue ring because it is the one we read from; node n2 is neither. The write set and the read set never touch — so the read misses the write entirely, and the caption records what a real Cassandra actually returned at consistency level ONE: u1 given as v1-ORIGINAL, a stale value, on a read that succeeded without any error. On the right, in green, the setting W = 2 and R = 2: two plus two is four, which IS greater than three. Now n1 and n2 both hold the write, and n2 and n3 are both read from — so n2 is filled violet and labelled BOTH, the overlap. The two sets are FORCED to share a node, every single time. A legend explains the colours: green means the node got the write, a dashed blue ring means we read from it, and violet means both, the overlap. The closing law states the honest limit: R + W greater than N guarantees your read TOUCHES the write, but it does not guarantee what that node KNOWS.

Three Numbers

Forget consistency for a second. Just count.

  • N — how many copies of each piece of data exist. Cassandra calls this the replication factor. Say N = 3: every row lives on three machines.
  • W — how many of those copies must say "got it" before you tell the user the write succeeded.
  • R — how many of those copies must answer before you trust the value you're about to hand back.

The first thing to notice is what's not here: nowhere does it say W must equal N. You do not have to wait for every replica. That's the entire point. If you had to hear from all three, then one sick machine would take down every write in your system — which is exactly the trap we walked into in Sync vs Async Replication & Failover, where a healthy leader stopped committing because a single named follower had died.

So we let a write succeed on a subset. Which immediately creates the problem this lesson exists to solve: if the write only went to some nodes, and my read only asks some nodes — what stops me asking the wrong ones?

The Pigeonhole: Why R + W > N Works

Nothing stops you asking the wrong ones. Unless you make it arithmetically impossible.

Picture the three replicas as three boxes. A write lands in W of them. A read reaches into R of them. The question — the only question — is whether those two handfuls are guaranteed to share a box.

If R + W > N, they must.

And the proof is something you already know, even if nobody ever told you its name. It's the pigeonhole principle: you cannot put more pigeons into fewer holes without doubling up. If you pick 2 boxes for the write and 2 boxes for the read, that's 4 picks spread across only 3 boxes — so at least one box got picked twice. There is no clever arrangement that dodges it. There is no unlucky day where it fails to happen. It is not a heuristic or a probability; it is counting.

That doubly-picked box is a node that (a) received the write, and (b) is in the set you're now reading from. So your read touches the latest value. It's in the pile of answers coming back to you.

The classic setting drops straight out of it: N = 3, W = 2, R = 2. Two plus two is four, four is greater than three, done. And notice how modest that is — you're not demanding everything from anyone. You need two of three to accept a write, and two of three to answer a read. A machine can be on fire and you are completely fine.

That's the beautiful part, and it's genuinely worth sitting with, because a one-line inequality just gave you a guarantee out of a system where every individual component is unreliable.

Now — and I want to be honest with you early rather than clever later — read that guarantee again very carefully. It says your read touches a node that has the write. It does not say your read returns the latest value. Those are different sentences, and the distance between them is where the rest of this section lives. Hold that thought; we'll come back and break it on purpose.

The Same Three Numbers Also Decide Who May Die

Here's what makes N/R/W worth learning properly rather than memorising: you didn't just configure consistency. You configured your availability and your latency at the same time, with the same numbers. Most people never notice.

Availability. A write needs W acknowledgments. There are N replicas. So a write survives exactly N − W dead nodes. A read needs R answers, so it survives N − R. With the classic N=3, W=2, R=2, you can lose one machine and carry on doing both — which is precisely why that setting is everywhere.

Watch it happen. I killed nodes one at a time on a real three-node cluster and asked for each consistency level in turn:

  nodes alive     ONE (R=1)    QUORUM (R=2)   ALL (R=3)
  ------------------------------------------------------
     3 of 3        works         works         works
     2 of 3        works         works        *FAILS*
     1 of 3        works        *FAILS*        FAILS

  Cannot achieve consistency level QUORUM
  info = {'required_replicas': 2, 'alive_replicas': 1}

N − R tolerated failures. Exactly as the arithmetic says. And look at ALL — R = N — sitting there tolerating zero failures. One machine goes down and every single read fails.

Which should feel familiar, because it's the same mistake in a new costume. In Sync vs Async Replication & Failover we watched a perfectly healthy leader refuse to commit because one named follower had died. ALL is that, generalised. Demanding everyone means depending on everyone. The paranoid-looking setting is the fragile one.

And this is the fix I promised you in that lesson: don't require node B. Require any two of three. Now node B can die on a Sunday and nobody gets paged, because you never needed that node — you needed enough nodes.

Latency. Same numbers again. You wait for the W-th fastest acknowledgment, not the slowest. With W=2 of N=3, one node having a terrible day — a long GC pause, a slow disk, a bad network hop — cannot slow you down, because by the time it's struggling you already have your two answers and you've moved on. That insulation from stragglers is a real, underrated gift.

Unless, of course, you throw it away by demanding to hear from everybody:

  20 reads at each consistency level (3-node cluster):

    ONE      731 ms
    QUORUM   793 ms
    ALL    1,169 ms      <-- 1.6x slower than ONE

ALL is 1.6× slower, and the reason is exactly the one you'd guess: when you insist on hearing from every replica, you finish at the speed of your worst one. Every extra node you demand an answer from is another chance to be held hostage by whichever machine is having the worst day.

The Four Settings of the Dial

So you have three numbers and they buy three different things. Here's the whole design space, and each row is a real, defensible choice that some real company is running right now.

The four settings of the N/R/W dial on three replicas, laid out as a table of trades, because the same three numbers set your consistency, your fault tolerance and your latency at once. Row one, W=1 and R=1, in red: 1 + 1 = 2, which is not greater than 3, so there is NO GUARANTEE. It is the fast-and-loose setting, fastest, and it survives two deaths either way, but stale reads are on the menu. Row two, W=2 and R=2, in green: 2 + 2 = 4, greater than 3, GUARANTEED. This is the quorum, and the row is marked start here: it buys guaranteed overlap and survives one death each way, and it costs a hair more latency, that is all. Row three, W=3 and R=1, in amber: guaranteed. Write-all, read-one makes reads free, ask any node, but one dead node blocks EVERY write. Row four, W=1 and R=3, in violet: also guaranteed. Write-one, read-all makes writes instant, but one dead node blocks EVERY read. Beneath, the measured numbers from a live three-node Cassandra cluster: 20 reads took 731 ms at ONE, 793 ms at QUORUM, and 1,169 ms at ALL, because you wait for the W-th fastest replica, so ALL waits for your worst one. The closing law: demanding everyone means depending on everyone — a quorum is the robust choice, not ALL.

W=1, R=1 — fast and loose. 1 + 1 = 2, which is not greater than 3. No overlap. Stale reads are not merely possible; they are on the menu. This is what produced v1-ORIGINAL at the top of the lesson. In exchange, it's the fastest and most available thing you can build — writes succeed if any node is alive, reads too. Perfectly correct for a page-view counter. Absolutely not for a shopping cart.

W=2, R=2 — the quorum. 4 > 3. ✓ Overlap guaranteed, one node may die on either side, and you're insulated from stragglers. This is the default answer, it is the right answer surprisingly often, and if you have no strong reason to pick something else, pick this.

W=3, R=1 — write-everywhere, read-anywhere. 3 + 1 = 4 > 3 ✓, so it's a valid quorum. Reads are gloriously cheap: ask any node, it's guaranteed current. Great for read-heavy workloads where writes are rare. And the bill arrives on the write path — W = N means one dead node blocks every single write. You've rebuilt the trap from the previous lesson on purpose.

W=1, R=3 — write-anywhere, read-everywhere. Also valid (1 + 3 = 4 > 3 ✓). Writes are instant, and reads must hear from all three — so one dead node blocks every read, and every read runs at the speed of the slowest replica. Rare, but it's the right shape if writes are constant and reads are precious.

Notice the symmetry: you're moving cost between the read path and the write path, and the total doesn't go down. Whatever you refuse to pay when you write, you pay when you read. There is no setting in the middle that quietly gives you everything, and if you find yourself reaching for one, you've misread the arithmetic.

One important footnote, because it trips people up constantly: CONSISTENCY ONE does not mean "write to one node." The coordinator sends the write to every live replica — W is just how many must come back and say "got it" before you're told the write succeeded. So in practice a CL=ONE write often does reach all three. The arithmetic uses W because W is what you can count on when things go wrong, and things go wrong.

See It / Drive It

Three numbers, three consequences, one inequality. It's much easier to feel than to read about.

Below you have a live ring. Set N, W and R. The write set and the read set light up, and you can watch the overlap appear and disappear as you move the dial. Every number the widget shows you — the guarantee, the failures you can absorb, the latency — is computed from the same arithmetic in this lesson, not hard-coded.

Try this first, because it reproduces the Cassandra result exactly: set N=3, W=1, R=1. The overlap indicator goes red — 1 + 1 is not greater than 3. Now write a value, then read it, and keep reading. Sooner or later you will get the old value back, and the widget will show you precisely which node lied to you and why it was entitled to. Then nudge R up to 2 and watch the guarantee snap into place.

After that, set W = N and kill a single node. Every write in your system stops. That's the trap from the last lesson, and you just rebuilt it with a slider.

The N/R/W Dial — tune the three numbers, kill nodes, and pick your own read set. Try to manufacture a stale read; then set R + W > N and discover you cannot.

The Honest Part: Overlap Is Not Freshness

Now let's break it.

R + W > N guarantees that your read touches a node holding the latest write. It's a claim about which machines you contacted. It is emphatically not a claim about what those machines know, and it is not a claim about what value you get back. Almost everybody makes that leap, and quorums do not earn it.

Here is where the guarantee leaks, and none of these are exotic:

Sloppy quorums. A network partition means the client can't reach the N nodes that are supposed to hold this data. Rather than fail the write, many systems will accept it on whatever nodes they can reach — nodes that aren't among the designated home replicas at all. Your write quorum and your read quorum are now drawn from completely different sets of machines. The overlap guarantee isn't weakened; it is simply void. (Those temporarily-misplaced writes get delivered later — that's Read Repair & Hinted Handoff.)

Concurrent writes. Two clients write the same key at the same moment, to overlapping-but-different sets of nodes. Your read touches a node with a latest write. Which one is the latest? There is no global clock and no leader to decide — and if the tiebreak is "whichever timestamp is bigger," then clock skew between machines can hand the win to the write that actually happened first. Overlap delivered you a value. It never promised the value was right. (That's the whole of Version Conflicts.)

Partial write failure. The write reached fewer than W nodes, so the client was told it failed — but the nodes that did get it don't roll it back. Now a subsequent read may or may not surface a write that officially never happened.

A replica dies and is rebuilt from a stale one. The number of nodes holding the latest write quietly drops below W. Nothing errors. The condition R + W > N is still true on paper, and it is now false in fact.

So what do you have? Something genuinely useful and worth naming precisely: with R + W > N and no concurrent writes, a read will see the most recent completed write. That's real, and it's most of what you want most of the time. It is not linearizability, it is not "strong consistency," and if you say those words in an interview about a Dynamo-style system, a good interviewer will pull the thread.

Which is exactly why this section keeps going. The next lesson gives you the actual vocabulary for what you do get and how stale it may be. The one after that tells you what happens to all of this when the network splits. The quorum is the foundation. It is not the whole building.

Choosing, Honestly

Start at N=3, W=2, R=2 and make somebody argue you out of it. Overlap guaranteed, one node may die on either side, stragglers can't hurt you, and the latency is a rounding error above the cheapest setting (793 ms vs 731 ms across twenty reads). It is the default for good reasons.

Move to W=1, R=1 when a stale read costs you nothing. View counters, feeds, telemetry, "likes", presence indicators. Be explicit that you are choosing this, and be explicit about what it means: you will serve old data, and you will not be told when. That's not a risk you're accepting, it's a behaviour you're purchasing.

Push W up only when writes are rare and reads must be cheap — and then look hard at the fact that W=N means one dead machine stops your writes. Almost every time someone reaches for ALL, what they actually wanted was QUORUM.

And say the honest sentence out loud. Not "we use quorums, so we're consistent" — that sentence is wrong and a good interviewer will know it. The sentence is: "We run N=3, W=2, R=2. Reads see the latest completed write as long as writes aren't concurrent. We tolerate one node failing on either path. Under a partition we may take sloppy writes, and then the overlap guarantee doesn't hold until they're handed back."

That's what it means to actually understand a quorum, as opposed to knowing the formula.

Try It Yourself

You can make a real database hand you stale data on purpose in about ten minutes, and you will never forget the shape of it afterwards. Everything below is what I actually ran.

Stand up a three-node Cassandra cluster, then turn off the two mechanisms that would otherwise quietly heal the gap you're about to create — because their job is to hide exactly the thing you're trying to see:

-- on every node: stop hints being replayed later
nodetool disablehandoff

-- and turn off read repair for this table
CREATE KEYSPACE shop WITH replication =
  {'class':'SimpleStrategy', 'replication_factor': 3};       -- N = 3

CREATE TABLE shop.cart (id text PRIMARY KEY, items text)
  WITH read_repair = 'NONE';

INSERT INTO shop.cart (id, items) VALUES ('u1', 'v1-ORIGINAL');

Now manufacture the stale read. Predict each step before you run it.

-- 1. take node3 out. It is about to miss a write.
docker stop cas3

-- 2. write with W = 1. It SUCCEEDS — the client is told 'ok'.
CONSISTENCY ONE;
UPDATE shop.cart SET items = 'v2-NEW-CART' WHERE id = 'u1';

-- 3. bring node3 back. Nothing repairs it — we turned that off.
docker start cas3

-- 4. now stop the OTHER two, so node3 has to answer from its own copy.
--    R = 1, W = 1, N = 3  ->  1 + 1 = 2, which is NOT > 3.
CONSISTENCY ONE;
SELECT items FROM shop.cart WHERE id='u1';

--    u1 | v1-ORIGINAL       <-- there it is. Stale, and perfectly happy about it.

-- 5. ask the same node for a QUORUM instead:
CONSISTENCY QUORUM;
SELECT items FROM shop.cart WHERE id='u1';

--    Cannot achieve consistency level QUORUM
--    info = {'required_replicas': 2, 'alive_replicas': 1}

Step 5 is the one to sit with. The database could have answered you. It had a value right there in memory and it was perfectly capable of returning it. It chose to raise an error instead, because you had asked for a guarantee it could no longer keep.

That error message is not a failure. It's the system being honest with you — which is more than the ONE read did.

Then bring the cluster back and watch the arithmetic do its job: with two of three alive, a QUORUM read (R=2, W=2, so 4 > 3) is guaranteed to touch a node holding v2-NEW-CART, and it returns it every single time.

Mental-Model Corrections

  • "R + W > N means my read always returns the latest value." It means your read touches a node that has the latest write. Concurrent writes, sloppy quorums and partial failures all break the leap from touches to returns. Touching is not knowing.
  • "Quorums give me strong consistency." They don't. Quorum systems are not linearizable — DDIA is explicit about this. What you get is: a read sees the most recent completed write, in the absence of concurrent writes. Say that sentence, not the short one.
  • "A quorum means a majority." A majority is the most useful quorum, not the definition. W=3, R=1 on N=3 is a perfectly valid quorum pair (4 > 3) and it isn't a majority read at all.
  • "ALL is the safe setting." ALL tolerates zero node failures (measured: it fails the moment one of three nodes drops) and runs 1.6× slower because you finish at the speed of your worst replica. It's the fragile setting.
  • "CONSISTENCY ONE writes to one node." No — the coordinator sends the write to all live replicas. W is how many must acknowledge before you're told it worked. Do the arithmetic with W, because W is what you can count on when a machine is missing.
  • "A Cannot achieve consistency level QUORUM error means something is broken." It means the system is keeping its promise: it would rather refuse than lie. Compare that with the ONE read in this lesson, which lied without blinking.
  • "Turning R and W up is just... better." Every notch you add on one path is availability and latency you spent. The total cost doesn't shrink; it moves.

Key Takeaways

  • Three numbers: N (how many copies), W (how many must ack a write), R (how many must answer a read). You never need W = N — that's the whole point.
  • R + W > N guarantees overlap, by the pigeonhole principle. You cannot pick W boxes and R boxes out of N without doubling up once W + R exceeds N. It isn't a probability. It's counting.
  • The classic N=3, W=2, R=2 (4 > 3) gives you overlap and survives one dead node on both paths. Start here.
  • The same three numbers set your availability: writes survive N − W failures, reads survive N − R. Measured on a real cluster: ONE works with 1 of 3 alive; QUORUM dies at 1 of 3; ALL dies at 2 of 3. R = N tolerates zero failures.
  • And your latency: you wait for the W-th fastest, so a straggler can't hurt you — unless you demand ALL, which finishes at the speed of your worst replica (measured 1,169 ms vs 731 ms).
  • This is the fix from the last lesson. "Require any two of three" instead of "require node B" is why one follower dying no longer stalls your writes.
  • The honest limit: overlap is about which nodes you TOUCH, not what they KNOW. Sloppy quorums void it, concurrent writes muddy it, partial failures leak through it. Quorums are not linearizable. What you get is: a read sees the latest completed write, absent concurrent writes.
  • A refused read is a feature. Cannot achieve consistency level QUORUM is the database declining to lie to you. The ONE read had no such scruples.

Next — The Consistency Spectrum: we've now said "stale," "latest," and "strong consistency" a dozen times each without ever defining them properly, and I've been quietly cheating. It turns out there's a whole ladder of guarantees between linearizable and eventual, each with a real name and a real cost — and knowing which rung you're standing on is the difference between a system you can reason about and one you merely hope about.