Module P-10·34 min read

What CAP actually claims, the three things it is routinely misquoted as claiming, and the latency trade-off it leaves out entirely.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module P-10 — CAP and PACELC

What this module covers: CAP is the most cited and least accurately quoted result in distributed systems. This module states it precisely — during a network partition you choose between linearizability and availability — then dismantles the three misreadings that make it useless in design reviews: that you "pick two of three", that CA is an option, and that it says anything about performance. It then covers why a GC pause is indistinguishable from a cut cable, and why PACELC — which adds the else case, where you trade latency against consistency on every single request — is the framework you actually make decisions with. Finishes by classifying real systems and naming what each one pays.


The Theorem Only Speaks During a Partition

CAP gets invoked in architecture reviews as if it were a personality quiz: we're an AP shop, we picked availability. That framing is wrong in a way that matters, because it makes the theorem sound like a philosophy when it is a narrow impossibility result about one specific situation.

Here is the whole statement, and it is worth being able to recite:

When the network partitions — when some nodes cannot reach other nodes — a distributed system must choose between remaining consistent and remaining available. It cannot be both.

That is it. Not "pick two of three". Not a claim about throughput. A conditional statement whose antecedent is there is a partition right now. When there is no partition, CAP is silent — it permits a system to be both perfectly consistent and perfectly available, and plenty of systems are.

The proof is almost insultingly simple, which is why the theorem is true and why arguing with it is a waste of a meeting. Take two nodes, A and B, holding a replica each of the same value x = 0. The link between them dies. A client writes x = 1 to node A. A second client reads x from node B.

Node B has exactly two options:

  1. Answer with 0. It has responded, so it is available. It has returned a value that a linearizable register would not have returned, because the write to A completed before the read to B began. Consistency lost.
  2. Refuse to answer — block, or return an error — until it can reach A again. Consistency preserved. It did not respond, so it is not available.

There is no third option. No amount of engineering creates one, because the information about the write is on the other side of a link that does not carry information. This is not a limitation of current databases; it is a limitation of causality.

Analogy: two ticket counters at opposite ends of a stadium, sharing one seating chart, connected by a single phone line. The line goes dead. A customer walks up to counter B and asks for seat 14A. Counter B can sell it — and risk that counter A sold it thirty seconds ago, producing two people with a claim to one seat. Or it can say "I can't sell anything until I can reach the other counter," and the queue goes home. It cannot both sell the seat and guarantee the seat is free. The phone line is the only thing that ever made that guarantee possible.


What the Three Letters Actually Mean

Most of the confusion around CAP is vocabulary, not logic. Each letter means something narrower and stranger than its everyday sense.

C is linearizability. Every read observes the most recent completed write, as though there were exactly one copy of the data and all operations happened one at a time in some order consistent with real time. Note what this is not: it is not ACID's C, which is about constraints and invariants inside a transaction. Module P-1 covered that collision — two unrelated properties sharing a letter — and it remains the single most common source of nonsense in CAP discussions. When someone says "we need CAP consistency because we have foreign keys," they have merged two different guarantees.

A is availability in an unusually strict sense: every request that reaches a non-failing node receives a non-error response, eventually, with no time bound. This definition is strict in one direction and absurdly generous in another. Strict, because a system that returns 503 on 0.01% of requests is not available in CAP's sense at all. Generous, because a node that answers after four minutes is available in CAP's sense and useless in yours. Your SLO's availability (Module O-2) is a completely different measurement — a ratio over a window, with a latency threshold baked in. A system can be CAP-available and blow every SLO it has.

P is partition tolerance, and this is the letter people get most wrong: it is not a feature you build. It is an assumption about the environment — that the network is allowed to drop and delay messages arbitrarily. You do not get to decide whether your network does that. You only get to decide what your system does when it happens.

LetterEveryday readingWhat CAP means
C"The data is correct / constraints hold"Linearizability — one logical copy, real-time ordering
A"Our uptime is good"Every request to a live node gets a non-error answer, eventually
P"We handle network faults gracefully"The network may lose messages — a property of the world, not the system

Once P is understood as an assumption rather than a capability, "pick two of three" collapses on contact.


Three Things CAP Does Not Say

1. It is not a design style, and you do not "pick two." The three-way Venn diagram — the one on every slide deck — implies you sit down and select two properties as a strategy. But you do not select P; the network selects it for you. The actual decision surface is one binary choice, taken at the moment a partition is detected, and taken separately for each operation: refuse, or serve possibly-stale data. Everything else in the diagram is scenery.

The practical consequence: a statement like "we're an AP system" is nearly content-free. The useful version names the operation and the behaviour. When the primary is unreachable, the cart-add endpoint accepts writes into the local replica and reconciles later, accepting that two devices can add the same item twice; the checkout endpoint returns 503 rather than charge against inventory it cannot verify. Same system, both branches, per operation. That is a design; "we're AP" is a bumper sticker.

2. CA is not an achievable option for a distributed system. This is the most consequential misreading, because it lets a team believe they have opted out. A "CA system" would be one that is both linearizable and available even during a partition — which the two-node proof above rules out. What "we chose CA" means in practice is: we did not decide what happens during a partition. And an undecided system does not get to be both. It gets whatever its defaults produce, which is usually the worst of both: a node that hangs on a lock it cannot release (unavailable) while a second node accepts conflicting writes (inconsistent). You lose C and A simultaneously, and discover it during the incident rather than during the design review.

There is one honest case that looks like CA, and it is worth naming precisely because it is so common: a single-node database is not a distributed system, so CAP has nothing to say about it. One Postgres instance with no replicas has no internal network to partition. It is trivially linearizable and its availability is bounded by exactly one machine's uptime plus however long a restore takes. That is a real and often correct architecture. But the moment you add a streaming replica and route any read to it, you have built a distributed system and inherited the choice — asynchronous replication means that replica can serve a value the primary has already superseded, and a failover across a partition can lose acknowledged writes outright (Module P-5's split-brain).

3. CAP says nothing whatsoever about performance when the network is healthy. This is the misreading that does the most day-to-day damage, because it gets used to explain latency. Our p99 is 400ms because we're a CP system, that's CAP. No. CAP permits a CP system to answer in one microsecond when there is no partition. If your reads are slow on a normal Tuesday, the theorem is not involved — something else is, and that something else is what the second half of this module is about.

Why this matters in production: partitions in a single well-run datacentre are rare — occasional minutes per year. If CAP were the whole story, the consistency-versus-availability trade would be an edge case you handle in a runbook and otherwise ignore. Teams reason as though that were true, and then cannot explain why their strongly-consistent reads cost 12ms instead of 0.4ms when nothing is broken. CAP is the rare case. The trade-off you are actually paying for, on every request, all year, is the one CAP does not mention.


A Partition Is Whatever Your Peers Cannot Distinguish From One

Before getting to that, correct one more mental model: the picture of a partition as a backhoe through a fibre bundle. Cable cuts happen, but they are a minority of the partitions your system will actually experience, and the picture makes people underestimate the frequency badly.

A partition, operationally, is node X cannot get a timely response from node Y. Everything in this list produces exactly that observation, indistinguishable from the outside:

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.