Filter concepts by levelShowing all levels.

System Design · Section 42

PACELC

Level
intermediate
Read
15 min
Concepts
3

CAP theorem only describes what a distributed system gives up during a network partition: availability or consistency. PACELC — Daniel Abadi's 2010/2012 extension — points out that the far more common case, normal operation with no partition at all, forces its own trade-off between responding quickly (Latency) and making sure replicas agree before responding (Consistency). A nearest-replica read or a low write-concern write is fast but possibly stale; waiting for a quorum or majority acknowledgment is current but pays the round trip to the slowest required replica — neither involves a partition. Evaluating a real system means asking two independent questions in order — partition behavior (PA or PC), then normal-operation default (EL or EC) — and checking whether specific operations can override the default, since many real systems are tunable per request rather than fixed system-wide.

This section

What is true here

  1. PACELC extends CAP with an "Else" branch: with no partition, a system still trades Latency against Consistency.
  2. The partition-time choice (A vs C) and the normal-time choice (L vs C) are independent — a system's CAP letter says nothing about its everyday latency behavior.
  3. A nearest-replica read or low write-concern write is fast but possibly stale; a quorum-acknowledged write or primary read is current but slower — a pure, partition-free trade-off.
  4. Evaluate a real system with two ordered questions — partition behavior, then normal-operation default — and watch for per-request overrides that shift only one operation's answer.

What you will be able to do

  • Explain why CAP theorem alone does not describe a replicated system's everyday behavior
  • Trace a concrete example of the latency/consistency trade-off in a fully healthy, partition-free cluster
  • Classify a real replicated system's PACELC behavior using the two-question checklist, including per-operation overrides

PACELC extends CAP

Why CAP alone leaves the far more common, partition-free case unaddressed, and the everyday trade-off PACELC names for it.

PACELC extends CAP to normal operation

coreintermediate

CAP theorem only describes what a distributed system must give up during a network partition: availability or consistency. PACELC — coined by Daniel Abadi in 2010 and formalized in a 2012 paper — points out that CAP leaves the far more common case unaddressed: when there is no partition at all, a replicated system still has to choose between responding quickly (Latency) and making sure every replica agrees before responding (Consistency). The name spells out the full rule: if there is a Partition, choose Availability or Consistency; Else (normal operation), choose Latency or Consistency. A system's partition-time and normal-time choices don't have to match, and in practice a design is usually described by both letters at once, e.g. "PA/EL" or "PC/EC".

Think of it as

CAP is like asking what a restaurant does during a kitchen fire (the partition): keep serving food that might be wrong, or stop serving until things are sorted out. PACELC adds the question every restaurant faces on an ordinary busy night with no fire at all: does the kitchen fire a dish the moment one cook finishes it (fast, but the other cooks on that table haven't confirmed their parts are ready), or does it wait for every cook on that ticket to confirm before any plate leaves the pass (slower, but the whole table arrives correct and together)? That second trade-off is there every single night, fire or no fire.

text
PACELC:
  if Partition:
    choose Availability or Consistency   (this part is CAP)
  else (no partition, normal operation):
    choose Latency or Consistency        (this part is new)

Common labels combine both branches, e.g.:
  PA/EL — available under partition, low-latency normally
  PC/EC — consistent under partition, consistent normally

What we're doing: Show that the "Else" branch applies even when a system has never experienced a partition.

pacelc-branches.txttext
Day 1, no partition: a write is sent to a
primary and 2 replicas.
  Option A: primary replies once it has written
    locally.        -> low latency, replicas may
                        lag briefly (chose L)
  Option B: primary waits for both replicas to
    ack before replying.
                     -> higher latency, all copies
                        agree at reply time (chose C)

Day 47, a network partition splits the replicas
from the primary.
  Option A: primary keeps accepting writes anyway.
                     -> stays available (chose A)
  Option B: primary refuses writes until the
    partition heals.
                     -> stops serving (chose C)

The Day 1 choice and the Day 47 choice are made
independently -- a system can pick differently in
each branch.
3
Option A on Day 1 is the "Else" branch of PACELC in action: no partition exists, yet the system still trades away some consistency for lower latency.
11
Day 47 is the classic CAP scenario — a real partition forces a choice between staying available and staying consistent.
19
The point of PACELC: the Day 1 (Else) decision and the Day 47 (Partition) decision are two separate design choices, not one.

Why this works: CAP alone would leave the Day 1 scenario completely undescribed, since no partition is happening — but that ordinary, partition-free case is where a replicated system spends nearly all of its time, so it is the trade-off engineers hit most often in practice.

Believing a system that is "CA" (or "CP", or "AP") under CAP has said everything about its behavior

Wrong

text
"This database is CP under CAP, so it must
be slow — consistency always costs latency,
right?"

Better

text
"This database's CAP letter only describes
partition behavior. To know its everyday
latency/consistency trade-off, I need its
PACELC classification too — e.g. is it PC/EC
(consistent and slower normally) or does it
actually relax to EL when there's no partition?"

What you see: A design discussion cites "CP" or "AP" as if it fully describes a system's performance characteristics under normal load, and is surprised when the system's everyday latency doesn't match that expectation.

Why: CAP's letters say nothing about behavior outside a partition — a system's CAP classification and its PACELC classification are answering two different questions, and both are needed for a complete picture.

PACELC: two independent branches
checkyeselse

A replicated request

Partition?

CAP's question

A or C

availability vs consistency

L or C

latency vs consistency

  • A replicated request
    • leads to Partition? (check)
  • Partition? — CAP's question
    • leads to A or C (yes)
    • leads to L or C (else)
  • A or C — availability vs consistency
  • L or C — latency vs consistency

CAP vs PACELC — what each one actually describes

CAP vs PACELC — what each one actually describes
TheoremConditionThe trade-off it names
CAPOnly while a partition is happeningAvailability vs Consistency
PACELC — "PA" or "PC" branchWhile a partition is happeningAvailability vs Consistency (same as CAP)
PACELC — "EL" or "EC" branchElse: normal operation, no partitionLatency vs Consistency

Remember: CAP only speaks during a partition (A vs C). PACELC adds the "Else": even with zero partitions, every replicated system trades Latency against Consistency on every single request — the two choices (partition-time and normal-time) are independent.

See also: worked example nearest replica vs quorum · pacelc as evaluation checklist · primary replica and sync vs async

Worked example: nearest-replica read vs quorum-ack write

coreintermediate

Take a replicated database running completely normally — no partition anywhere. Reading from the geographically nearest replica returns fast, but that replica might be a few hundred milliseconds behind the primary, so the read can be stale. Waiting for a quorum (a majority of replicas) to acknowledge a write before confirming it guarantees that a later read will see it, but every write now pays the round-trip latency to the slowest replica in that majority. Neither option involves any partition; both are pure, everyday latency-versus-consistency choices — exactly the "Else" branch PACELC names.

Think of it as

This is like choosing between texting a friend nearby who might not have checked their phone yet (fast, but maybe stale — like a nearest-replica read) versus getting a live three-way conference call confirmation from a majority of your friend group before you consider information "settled" (slower, since you wait for the slowest person to pick up, but you know it's current). No one's phone is broken and no call has dropped — this is just the normal cost of getting more people to agree before you act on something.

javascript
// MongoDB — the same insert, two latency/consistency points
db.orders.insertOne(doc, { writeConcern: { w: 1 } });          // fast
db.orders.insertOne(doc, { writeConcern: { w: 'majority' } }); // durable, slower

What we're doing: Trace one write and one read through both the fast/available path and the consistent path, with no partition anywhere.

quorum-vs-nearest.txttext
Setup: 1 primary + 2 secondaries, all healthy,
all reachable. No partition.

WRITE, path 1 (low latency):
  app -> primary: insert({..}, {w: 1})
  primary applies locally, replies "ok"     <- ~5ms
  secondaries catch up asynchronously,
    a beat behind

WRITE, path 2 (consistent):
  app -> primary: insert({..}, {w: 'majority'})
  primary applies locally
  primary waits for 1 of 2 secondaries
    to durably ack
  primary replies "ok"                      <- ~40ms
  (slower: bounded by the slower of the
   two secondaries' ack time)

READ, path 1 (low latency):
  app -> nearest secondary: findOne(id)
  secondary answers from its own copy       <- ~5ms
  (might not yet reflect the write above,
   if that secondary hasn't replicated it)

READ, path 2 (consistent):
  app -> primary: findOne(id)
  primary answers from the source of truth  <- ~15ms
  (guaranteed to reflect any 'majority'-
   acknowledged write)
9
Path 1's write returns after only the primary applies it — fast, but the two secondaries are still catching up when "ok" comes back.
15
Path 2's write blocks on a majority ack (1 of 2 secondaries) before replying — the extra network round trip is the latency cost of that consistency guarantee.
21
Path 1's read goes to the nearest secondary and can return before that secondary has replicated the most recent write.
26
Path 2's read goes to the primary, guaranteeing it reflects any write that was itself acknowledged by a majority — at the cost of that extra hop and no geographic-proximity benefit.

Why this works: Every millisecond in this trace happens with a fully healthy, unpartitioned cluster — the entire latency difference between the two paths is the cost of insisting on stronger consistency, which is precisely the trade-off CAP theorem has nothing to say about.

Testing only in a single-region, low-latency environment and concluding "majority" write concern is free

Wrong

text
"w: 'majority' looked just as fast as w: 1 in
our local 3-node dev cluster, so let's always
use majority in production."

Better

text
"Our dev cluster's nodes are all on localhost
with sub-millisecond RTT, so the majority-ack
wait was invisible. In production, replicas
span regions with 40-80ms RTT — measure the
write-concern latency delta there before
deciding it's an acceptable cost everywhere."

What you see: A write-concern or quorum-consistency setting that looked free in local testing causes a visible latency regression once deployed against geographically distributed replicas.

Why: The latency cost of waiting for a quorum/majority ack scales with the round-trip time to the slowest member of that quorum — a low-RTT dev environment hides a cost that a multi-region production environment exposes in full.

No partition — pure latency vs. consistency

Fast (w:1, nearest read)

  • +Primary applies locally, replies ~5ms
  • +Nearest secondary answers from its own copy
  • +May not yet reflect the latest write

Consistent (w:majority, primary read)

  • Waits for a majority ack, ~40ms
  • Primary answers from the source of truth
  • Guaranteed to reflect any acknowledged write
  • Fast (w:1, nearest read)
    • Primary applies locally, replies ~5ms
    • Nearest secondary answers from its own copy
    • May not yet reflect the latest write
  • Consistent (w:majority, primary read)
    • Waits for a majority ack, ~40ms
    • Primary answers from the source of truth
    • Guaranteed to reflect any acknowledged write

Two everyday choices, same underlying trade

Two everyday choices, same underlying trade
SystemFast/available choiceConsistent choiceCost of the consistent choice
MongoDB writesw: 1 (primary only)w: "majority"Waits for a majority of replica-set members to durably ack
DynamoDB readsEventually consistent (default)Strongly consistent (ConsistentRead: true)Cannot be served by a GSI/stream; costs 2x the read capacity
Generic replica readNearest replicaRead from primary / wait for replica to catch upExtra network hop or wait for replication lag to close

Remember: Nearest-replica read or w:1 write = fast, possibly stale. Primary/quorum read or w:"majority" write = current, but pays the round-trip to the slowest required replica. No partition involved in either — pure Latency-vs-Consistency, PACELC's "Else" branch.

See also: pacelc as cap extension · pacelc as evaluation checklist · read replicas and consistency · replication lag

Advertisement

Applying PACELC

Using PACELC as a checklist to classify a real replicated system's behavior, both under partition and in normal operation.

Using PACELC as an evaluation checklist

standardintermediate

To evaluate any replicated system with PACELC, ask two separate questions in order: (1) "If a partition happens, does this system stay available (PA) or does it stay consistent (PC)?" and (2) "With no partition, does it favor low latency (EL) or consistency (EC) on the read/write path I care about?" The answers combine into a four-letter label like PA/EL or PC/EC. This works as a checklist precisely because the two questions are independent and neither one alone answers the other.

Think of it as

Using PACELC to evaluate a system is like reading two separate lines on a restaurant's health rating: one line for "what happens during a kitchen emergency" and a completely separate line for "how they run service on a normal Tuesday." A five-star normal-Tuesday rating tells you nothing about what they do during a fire, and vice versa — you need both answers, from both questions, to actually know what you're getting.

text
PACELC evaluation checklist for a replicated system:

1. Partition question:
   Under a network partition, does it stay
   available (PA) or stay consistent (PC)?

2. Normal-operation question (per read/write path):
   With no partition, does the default favor
   low latency (EL) or consistency (EC)?

3. Check for per-request overrides:
   Can a specific call opt into the other choice
   (e.g. a "strongly consistent" flag)?

Combine 1 + 2 into a label: PA/EL, PC/EC, PA/EC, PC/EL.

What we're doing: Walk the checklist end to end for DynamoDB's default configuration, then show how a single flag moves one operation to a different point on the trade-off.

dynamodb-pacelc-checklist.txttext
System under evaluation: Amazon DynamoDB (default config)

Q1 - partition behavior:
  DynamoDB is built to keep serving both reads
  and writes during infrastructure/network
  issues within its replication group.
  -> Answer: PA

Q2 - normal-operation default (GetItem, no flag):
  "Eventually consistent" is the default read
  type. Docs: "the responses might not reflect
  the results of a recently completed write."
  Also: eventually consistent reads cost half
  of strongly consistent reads.
  -> Answer: EL

Combined default label: PA/EL

Q3 - per-request override:
  GetItem / Query / Scan accept ConsistentRead:
  true, which returns "the most up-to-date data,
  reflecting the updates from all prior
  successful write operations" for that one call.
  -> That single call moves toward the EC side
     of the normal-operation question, at higher
     cost and latency; it does not change the
     partition-time (Q1) answer at all.
4
Q1 is answered from what the system is designed to do when a partition occurs — DynamoDB favors staying available.
11
Q2 is answered from the default, no-flag behavior of a normal read — eventually consistent is the default and explicitly documented as possibly stale.
21
Q3 shows the checklist applied per-operation: ConsistentRead:true only changes the answer to Q2 for that call, and never touches the Q1 (partition) answer — confirming the two questions really are independent.

Why this works: Running the checklist in order — partition behavior first, then normal-operation behavior, then checking for per-call overrides — is what turns "PACELC" from a memorized acronym into something that produces a specific, defensible label for a specific system and even a specific API call.

Giving a system one PACELC label without specifying which operation it describes

Wrong

text
"DynamoDB is PA/EL." (stated as if this
covers every possible call to it)

Better

text
"DynamoDB's default GetItem is PA/EL. The
same GetItem with ConsistentRead: true is
still PA (partition behavior doesn't change)
but shifts toward EC for that call, at extra
latency and cost — so 'PA/EL' describes the
default, not every call the system can make."

What you see: A design doc labels an entire database with one PACELC classification, then a teammate points out a specific query path (a strongly-consistent read, a majority-write) that clearly behaves differently from the label.

Why: Many real systems expose tunable consistency per request rather than one fixed system-wide behavior — collapsing that into a single label hides the specific configuration a design decision actually depends on.

The three-question checklist

Partition behavior

PA or PC?

Normal-op default

EL or EC?

Per-request override

e.g. ConsistentRead

  1. Partition behavior — PA or PC?
  2. Normal-op default — EL or EC?
  3. Per-request override — e.g. ConsistentRead

The two-question checklist, worked for DynamoDB

The two-question checklist, worked for DynamoDB
QuestionWhat to checkDynamoDB's answer
1. Partition behaviorDoes it keep serving reads/writes during a network partition, or refuse?Designed to remain highly available under partition — PA
2. Normal-operation defaultWhat does the default read/write path favor with no partition?Eventually consistent reads are the default, favoring latency — EL
2b. Normal-operation opt-inIs there a per-request way to trade latency for consistency?ConsistentRead: true switches that one read to strongly consistent, at higher latency/cost

Remember: Evaluate in two independent steps: (1) partition behavior -> PA or PC, (2) normal-operation default on the path you care about -> EL or EC. Watch for per-request overrides (like DynamoDB's ConsistentRead) that shift only the second answer, for one call, without touching the first.

See also: pacelc as cap extension · worked example nearest replica vs quorum · read replicas and consistency

Advertisement