You replicate data across 3 nodes for durability. A write comes in. Do you wait for all 3 to confirm? That’s slow and any one node going down blocks all writes. Do you confirm after just 1? That’s fast, but if that node dies before replicating, the data is gone.

Quorum systems let you pick the balance.

The Quorum Formula#

With N replicas, a write quorum W is the number of nodes that must acknowledge a write. A read quorum R is the number of nodes you must read from. The consistency guarantee comes from one rule:

W + R > N

If this holds, any read is guaranteed to overlap with at least one node that has the latest write. With N=3, W=2, R=2: two nodes confirm the write, you read from two nodes. At least one of your read nodes must have the latest data.

public class QuorumConfig {
    private final int replicas;     // N
    private final int writeQuorum;  // W
    private final int readQuorum;   // R

    public boolean isStronglyConsistent() {
        return writeQuorum + readQuorum > replicas;
    }

    // Common configurations for N=3:
    // W=2, R=2: balanced (most common)
    // W=3, R=1: strong writes, fast reads
    // W=1, R=3: fast writes, strong reads
}
graph TD CL["Client Write"] --> N1["Node 1: ACK"] CL --> N2["Node 2: ACK"] CL --> N3["Node 3: pending"] N1 --> Q{W=2 met?} N2 --> Q Q -->|Yes| OK["Write confirmed"] CR["Client Read"] --> N1R["Node 1: read"] CR --> N2R["Node 2: read"] N1R --> QR{R=2 met?} N2R --> QR QR -->|Yes| RES["Return latest value"] style CL fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style N1 fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style N2 fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style N3 fill:#000000,stroke:#ff0000,stroke-width:2px,color:#fff style Q fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style OK fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style CR fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style N1R fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style N2R fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style QR fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style RES fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff

Tuning the Knobs#

Write-heavy workload? Set W=1, R=N. Writes are fast (one ACK is enough). Reads must check all nodes to find the latest value. Useful when you write constantly but read rarely.

Read-heavy workload? Set W=N, R=1. Writes are slow (all nodes must confirm). Reads are fast (any single node has the latest data). This is essentially what synchronous replication gives you.

Balanced? W=2, R=2 with N=3. Most common setup. Tolerates one node failure for both reads and writes.

The consistency model you get depends entirely on these numbers. W + R > N gives you strong consistency. W + R <= N gives you eventual consistency, faster but with stale-read risk.

Sloppy Quorums#

Strict quorums require the designated replicas for a given key. If two of three designated nodes are down, writes fail even though you have other healthy nodes in the cluster.

Sloppy quorums relax this: write to any W available nodes, even if they’re not the “correct” ones for this key. The data reaches W nodes, just maybe not the right W. A background process (hinted handoff) later copies the data to the correct nodes.

More available but weaker consistency. A read might hit the correct nodes before hinted handoff runs, missing the latest write. This is the exact trade-off the CAP theorem describes.

At Oracle, we had a replication challenge with NSSF config data across regions. Config changes needed to propagate to multiple regional nodes. Initially, we waited for all nodes to confirm (W=N). A single slow or unreachable region blocked the entire update. Moving to W=2 out of 3 regions meant updates completed faster and tolerated one region being temporarily unreachable. The remaining region caught up via async replication. For config data that wasn’t latency-sensitive, this was perfectly acceptable. The 95% reduction in config time came partly from not waiting for the slowest region.

What I’m Learning#

Quorums turn consistency into a tunable parameter instead of a binary choice. The math is simple (W + R > N), but the implications are deep. Every distributed database lets you tune these numbers, and the right choice depends entirely on your read/write ratio and tolerance for stale data. It connects directly to read replicas: a read replica setup is essentially W=1 (write to primary only) with R=1 (read from any replica), which means W + R = 2 <= N. That’s why replicas can serve stale data.

How do you choose your quorum settings, and have you ever changed them based on workload patterns?