Skip to main content

CAP and PACELC Frameworks and When to Use Them

What This Concept Is

Two frameworks for reasoning about the tradeoffs distributed storage systems make.

CAP (Brewer, 2000; Gilbert and Lynch proof, 2002)

CAP states that in the presence of a network partition (P), a distributed system must choose between:

  • Consistency (C): every read sees the most recent write (more precisely, linearizability).
  • Availability (A): every request receives a (non-error) response.

Under a partition, you cannot have both. You must forfeit one. Systems are classified:

  • CP: chooses consistency. Under partition, minority side returns errors or blocks. Example: Spanner, ZooKeeper, HBase, etcd.
  • AP: chooses availability. Under partition, all sides continue to serve, accepting that they may temporarily diverge. Example: DynamoDB (in eventual mode), Cassandra, Riak.

CAP is only about behavior under partition. In normal (non-partitioned) operation, systems can be both C and A. This is the single most widely misunderstood point.

PACELC (Abadi, 2010)

PACELC extends CAP to include the latency/consistency tradeoff that exists even without a partition:

If Partition, then A vs C. Else, L vs C.

  • If there is a partition (P), trade Availability (A) vs Consistency (C).
  • Else (no partition), trade Latency (L) vs Consistency (C).

Systems are classified PA/EL, PC/EC, PA/EC, PC/EL. For example:

  • Spanner: PC/EC. Always consistent, even if it costs latency (TrueTime sync or availability loss under partition).
  • DynamoDB (default eventual reads): PA/EL. Always low latency, willing to sacrifice consistency under partition and in normal operation.
  • Cassandra (tunable): typically PA/EL at quorum, but you can configure per-operation.

PACELC is usually the more honest framing in practice, because partitions are rare in well-run data centers but latency tradeoffs happen on every request.

Why It Matters Here

Most engineers have heard "CAP: pick two" and conclude that distributed databases require picking consistency or availability in steady state. That is wrong and leads to bad architecture decisions. The two frameworks are for honestly naming the tradeoff when choosing or operating a system.

You will use PACELC to evaluate any distributed database, cache, queue, or KV store you are considering. You will use CAP when someone says "we need strong consistency" to clarify that they mean under partition, and to force the cost of that choice onto the table.

Concrete Example

CAP applied

You deploy a Postgres primary + synchronous replica across two regions. Normal operation: low-latency, linearizable writes (primary), linearizable reads (primary with fenced token). Under a partition between regions:

  • If you keep the primary serving only on one side and the other side returns errors: CP.
  • If you promote a new primary on both sides and keep serving: AP and split-brain on merge. You picked A, lost C, and you will need conflict resolution on heal.
  • If one side serves reads from a stale snapshot but no writes: a hybrid; you are still not linearizable, but you preserved partial availability.

There is no way to provide linearizable writes on both sides during a partition. That is CAP.

PACELC applied

Two systems, no partition in sight. Which is faster in steady state?

  • Spanner (PC/EC): reads and writes use Paxos groups. Writes need a majority ack; reads either go through the leader with a lease or require TrueTime-based commit-wait. Latency is significant (tens of ms cross-region).
  • DynamoDB eventual (PA/EL): reads can come from any replica without coordination. Latency is ~single-digit ms. Writes accepted locally and propagated.

Choosing between them is not a consistency question at all under PACELC: it is a question of whether the application tolerates stale reads in exchange for latency.

Common Confusion / Misconception

"CAP says pick two of three." It does not. In normal operation all three are simultaneously possible. CAP is only about what you give up under partition, and between C and A specifically.

"CP systems are unavailable under partition." They are unavailable on the minority side. The majority side continues to serve. Many systems make this tradeoff willingly; it is not a system-wide outage.

"PACELC replaces CAP." It extends it. You need CAP for the partition case (which P says nothing about, it just labels the choice), and PACELC for the steady-state latency/consistency question.

"Every AP system is eventually consistent." AP plus any convergence protocol is at least eventually consistent, but the AP label is about the partition-time choice, not about the absence of stronger guarantees in steady state.

"Stronger consistency always hurts availability." Under partition, yes. In steady state, stronger consistency usually costs latency, not availability. Do not conflate the two regimes.

How To Use It

When evaluating a new storage system, ask in order:

  1. PACELC label: what does the docs imply about P (A vs C) and E (L vs C)?
  2. Normal-operation latency: measured p50 / p99 for reads and writes with and without strong consistency options.
  3. Partition behavior: what happens on the minority side? does it error, stall, or diverge? what is the merge story?
  4. Operational definition of consistency: when docs say "strongly consistent," do they mean linearizable, serializable, or something else? For which operations?

Write the answer next to the system in your architecture notes. Do not paraphrase.

Check Yourself

  1. State CAP precisely. What is the one regime in which the tradeoff applies?
  2. Explain why a CP system is not the same as an "unavailable system under partition."
  3. Give the PACELC labels for (a) single-node Postgres, (b) DynamoDB with eventual reads, (c) Spanner.
  4. Why is "we need strong consistency" an incomplete requirement?
  5. Give one scenario where PACELC is a better framework than CAP.

Mini Drill or Application

For each system, give the PACELC label and justify:

  1. PostgreSQL, single primary, synchronous streaming replica, reads from replica.
  2. MongoDB, replica set with majority write concern, strong-read.
  3. DynamoDB with ConsistentRead=true.
  4. Apache Cassandra with CL=LOCAL_ONE reads, CL=LOCAL_QUORUM writes.
  5. Google Spanner with strong reads.

Then: for each, describe the behavior of a write and a read during a full cross-region network partition.

Read This Only If Stuck