The CAP Theorem

Under a Partition, You Pick Consistency or Availability

The CAP Theorem

CAP stated honestly — the partition tradeoff between C and A — why "CP vs AP" oversimplifies, and how PACELC adds the latency dimension.

8 min read Level 4/5 #system-design#cap-theorem#consistency
What you'll learn
  • State CAP correctly as a choice made only during a partition
  • Explain why CP/AP labels oversimplify real systems
  • Extend the model with PACELC's latency tradeoff

The CAP theorem is the most cited and most misquoted idea in distributed systems. The popular version — “pick two of Consistency, Availability, Partition tolerance” — is misleading enough to be wrong. Let’s state it the way that actually helps you design.

What the three letters mean

  • Consistency (C) — every read sees the most recent write. All nodes agree on the current value. (Note: this is linearizability, a stricter notion than the “C” in ACID — same letter, different idea.)
  • Availability (A) — every request to a non-failed node gets a (non-error) response, even if the data might be stale.
  • Partition tolerance (P) — the system keeps working when the network drops messages between nodes.

The honest statement

Here’s the part the “pick two” framing botches: in any real distributed system, partitions happen — networks fail, packets drop, links flap. So P is not optional. You don’t choose partition tolerance; the network imposes it on you.

Which means the real theorem is much narrower:

When a partition occurs, you must choose between Consistency and Availability. When there’s no partition, you can have both.

The choice only exists during a partition. Two nodes can’t reach each other; a write arrives. You have exactly two options:

The CAP Theorem — architecture diagram
  • CP — refuse or block writes until the partition heals, so nobody reads stale data. You stayed consistent at the cost of availability.
  • AP — keep accepting reads and writes on both sides, reconciling later. You stayed available at the cost of consistency (the sides temporarily disagree).

There is no third door. During a partition you cannot be both perfectly consistent and fully available — that’s the entire theorem.

Why “CP vs AP” oversimplifies

Labeling a database “CP” or “AP” is a useful shorthand but a leaky one, because:

  • It’s per-operation, not per-database. One system can offer strong consistency for some operations and eventual for others. Many modern databases let you choose the consistency level per query.
  • It’s a spectrum, not a switch. Between “every read is current” and “anything goes” lie many useful middle grounds (the next lesson’s consistency models).
  • Availability is graded. “Available” in CAP means any response — real SLAs care about latency and partial degradation, which CAP says nothing about.

PACELC: the missing half

CAP only describes the partition case — but partitions are rare. What about the 99.9% of the time the network is fine? PACELC completes the picture:

If Partition (P): choose Availability or Consistency (A/C). Else (E): choose Latency or Consistency (L/C).

The insight: even with no partition, strong consistency has a price — to guarantee every read is current, nodes must coordinate, and coordination costs latency. So the everyday tradeoff isn’t C vs A; it’s C vs L. A system that synchronously replicates to a quorum before acking is slower than one that acks locally and replicates lazily.

SystemPartition (P)Else (E)Reading
Dynamo / CassandraALavailable + low-latency, eventual
SpannerCCconsistent always, pays latency
MongoDB (replica set, majority)CAminority side rejects writes under partition; low-latency when healthy
Postgres (single primary)CCconsistent; not partition-tolerant by design

The JavaScript angle

You feel CAP/PACELC in the shape of your async code, not in theory. A write that waits for a quorum is a slower await than one that returns the moment the local node has it — the latency tradeoff is literally how long your promise takes to resolve:

Consistency vs latency, expressed as a write concern script.js
// MongoDB: the write concern *is* the PACELC dial, per operation.

// Low latency, weaker durability/consistency: ack as soon as the primary
// has it in memory. Fast `await`, but a crash can lose this write.
await orders.insertOne(order, { writeConcern: { w: 1 } });

// Stronger consistency/durability: wait for a majority of replicas to
// confirm before resolving. Slower `await` — you paid latency for safety.
await orders.insertOne(order, { writeConcern: { w: 'majority' } });
▶ Preview: console

The same line of JS, two different points on the PACELC curve — chosen per write. CAP tells you the tradeoff exists; the consistency models in the next lesson tell you the useful settings between the extremes.