lumo

Module 09 · Lesson 7 of 13Free

CAP and PACELC: core distributed tradeoffs

Level
Intermediate
Topic
Distributed systems: replication and consistency
Reading time
18 min

When you finish this page you can

  1. Explain why disconnected replicas cannot guarantee both linearizable reads and availability.
  2. Choose partition behavior for operations with different product requirements.
  3. Calculate the latency cost of a remote coordination step.
  4. Use PACELC to describe failure behavior separately from normal operation.

Builds on 3 lessons

Start with lesson 217 min
  1. Network partitions: when nodes cannot communicate17 min
  2. Consistency models: from strong to eventual18 min
  3. Read-your-writes consistency: always seeing your own updates18 min

Video lesson · coming soon

has 1 speaker left in a festival sale. A confirms its reservation for Asha. Replica B cannot communicate with A, but still shows the speaker as available.

Should B serve that answer to Ravi, or refuse his request?

Kartly now has separate services and replicated data. We’ll follow one product across two . The stock count and regional layout are illustrative assumptions for this lesson.

The central question is: when should a replicated service wait, refuse, or answer from local state?

Check yourselfAnswer in your head first, then reveal
Only A accepts writes. Does that make it safe for B to answer every stock read during a network partition?Show answerHide answer
No. A single writer prevents competing writes, but B can still return an old value after A confirms a change. The read policy matters as well as the write policy.

Diagram not drawn yet: cap-kartly-missing-reservation.svg

Asha reserves the last speaker through replica A and receives confirmation. Communication between replicas A and B is broken. After that confirmation, Ravi reads replica B, which still stores one available speaker. B must return its old value or withhold the stock answer.

B is running, but it lacks the information needed to answer a current-stock read.

The missing message creates the choice

Start with the simplest regional design. A accepts stock changes. It sends updates to B afterward. Nearby requests read their local copy.

This is the asynchronous copying pattern from Replication models. It works for browsing when temporary differences are acceptable.

Now follow one execution:

  1. Both replicas store remaining = 1.
  2. Communication between them stops.
  3. A reserves the speaker and stores remaining = 0.
  4. A confirms the reservation.
  5. Ravi’s read reaches B after that confirmation.

B sees the same local state in two possible histories:

History outside B What B stores
Nobody reserved the speaker remaining = 1
A confirmed Asha’s reservation remaining = 1

No local calculation distinguishes these histories. A clock cannot supply the missing reservation. Repeating the read only reads the same old copy.

If B returns 1, it is wrong in the second history. Guessing 0 is wrong in the first. Waiting for A may never finish if communication never returns.

This is the core impossibility argument: unavailable information prevents a service from guaranteeing both an atomic answer and completion everywhere.1

Adding replicas does not change that argument when the answering group cannot learn what the other group completed. We need to decide which promise this operation can give up.

CAP names precise promises

CAP combines , and tolerance. Its meanings are narrower than their everyday uses.

Letter Meaning here What it does not mean
C Operations behave like one copy, respecting real-time order Every replica always has identical bytes
A Every request at a non-failing eventually completes its specified operation Every request finishes within a target
P The model allows communication failures between groups of nodes Every feature keeps working during those failures

For CAP, consistency means : each operation appears to happen at one instant between its request and response.1 The earlier Consistency models lesson develops that contract.

Asha’s completed reservation must therefore precede Ravi’s later stock read. Operations that overlap can be ordered either way if the operation rules permit it.

A 503 response is useful failure handling, but it does not complete the requested stock read. Returning errors everywhere cannot satisfy CAP availability. A valid “sold out” result is different: it completes a reservation attempt according to the stock rules.

A permits messages to remain undelivered. If that can happen, the service cannot guarantee both C and A for the shared read/write object.1

“Choose any two” hides the problem

The common description is “choose any two of three.” That suggests Kartly can select consistency and availability, then choose not to have partitions.

But a configuration setting cannot make a broken link carry messages. During that failure, Kartly still needs a behavior. Brewer explicitly cautions against treating “two of three” as a complete design rule.2

Nor must a consistency-preserving service stop everywhere. One authorized side may continue working. The guarantee of completion at every non-failing node is what it gives up.

CAP tells us which combination is impossible. It does not tell us which failed requests customers should see.

Protect the promise, not every read

Kartly has two distinct product questions.

Must the product page show exact stock? No. An approximate availability label is acceptable if checkout checks again.

May two customers receive the same final reservation? No. One customer would pay and later lose the order.

For this example, a reservation is one atomic operation: check remaining stock and decrement it if positive. A read followed by a separate decrement would introduce a local race before replication even matters.

What should B do when it cannot reach the stock authority?

Confirm reservations using each region’s local stock.

Both regions can keep confirming reservations. Starting from the same final unit, each can promise it to a different customer. Repairing the count later cannot fulfill both promises.

Require authority access for every stock read.

Every stock-related screen waits for A. This gives a simpler freshness contract, but a regional link failure also prevents customers from browsing products they might buy later.

Why this choice

Keep A as the fixed reservation authority in this small model. B forwards reservation requests rather than deciding independently. A serializes conditional stock changes and stores each result before confirming it.

The limitation is deliberate: B cannot take over merely because A stops responding. A might still be serving customers. Automatic takeover needs a protocol that prevents competing authorities.

Choose stricter reads if the displayed value itself is a binding promise. Choose local acceptance only if the product permits tentative requests, backorders, or later rejection.

Calling a request “pending” changes the contract. It does not make a confirmed reservation available everywhere.

This choice applies to an operation, not Kartly as a whole. Brewer describes making partition choices at finer boundaries than an entire system.2

For the read/write reservation interface, we favor consistency during partitions: PC in notation. Approximate catalog reads deliberately offer a weaker contract. They are not evidence that the reservation interface is available everywhere.

The distinction gives the UI a concrete responsibility: never render an approximate browsing value as a confirmed stock hold.

Recovery cannot undo a promise

Suppose Kartly instead allowed both regions to reserve their local final unit.

A confirms Asha’s reservation. B confirms Ravi’s. Each local transaction may be valid against its own copy.

When communication returns, both copies might contain remaining = 0. Comparing only current values would hide the problem. The reservation records reveal two promises backed by one speaker.

Choosing one final database value does not repair the customer experience. Kartly must obtain more stock, cancel an order, or offer compensation.

Our chosen design avoids that particular conflict by refusing independent reservations at B. After reconnection, B catches up from A before it is eligible for any read contract requiring current state.

There is still another failure: A commits a reservation, but its confirmation never reaches the caller. A timeout must not be shown as proof that nothing happened.

Use a , a stable identifier for one reservation attempt. A stores the key and reservation result atomically. A retry returns that result instead of taking another unit. Idempotency covers the implementation.

The resulting behavior should be written down before deployment:

Situation Customer sees Detection and recovery
B cannot reach A Browsing works; reservation temporarily unavailable Record forwarding timeouts; retry communication
A commits but response is lost Confirmation status unknown Retry with the same key
B is behind after reconnection Approximate browsing data Track applied progress; catch up before strict reads
Fixed authority A crashes Reservations unavailable Restore A; promotion needs a safe authority-transfer protocol

This design does not promise survival of permanent loss of A’s storage. Replication durability and safe promotion are separate requirements.

We have chosen failure behavior. We have not yet chosen how much waiting customers experience when everything works.

Healthy networks still cost time

Imagine a seller changes a product description through A. B receives the update asynchronously.

Even with a healthy network, there is an interval when B still has the old description. We must either permit that read or make it wait for authoritative information.

PACELC makes the second question explicit:

  • If a partition occurs: availability or consistency?
  • Else: latency or consistency?

Abadi introduced this formulation to include tradeoffs outside network failures.3

Latency is not interchangeable with CAP availability. A request that eventually completes after a long wait may satisfy the formal availability condition and still be useless to a customer.

Consider two catalog read paths. The following timings are estimates for this lesson, not measured infrastructure performance.

Read the nearby copy

8 ms local round trip + 4 ms processing = 12 ms

B answers from local state. A recently acknowledged description change may be missing.

Read through the remote authority

12 ms local path + 80 ms remote round trip = 92 ms

B asks A instead. Assume A serves a linearizable read and no failover occurs.

Compare the paths

92 ms − 12 ms = 80 ms extra per read

In this simplified serial path, the remote dependency consumes 80 ms of the page’s .

The extra delay comes from this , not from the word “consistency.” Moving the authority closer would change it.

Diagram not drawn yet: pacelc-kartly-read-paths.svg

Two independent panels compare catalog reads. The local-copy panel shows a client reaching B and receiving a potentially old description in an estimated 12 milliseconds. The authority-read panel shows B asking A over an estimated 80-millisecond remote round trip, for an estimated total of 92 milliseconds.

Both networks are healthy. The difference is whether the read depends on a remote answer.

Should every catalog read pay for an authoritative answer?

Route every catalog read to the authority.

Reads go through A’s linearizable interface. Customers see completed edits in real-time order, but remote readers pay the added round trip and depend on A.

Use different read contracts for browsing and editing.

Ordinary browsing stays local. A seller’s preview uses the authority after an edit. That gives the seller a stronger experience without making every shopper’s read remote.

Why this choice

For this browsing path, choose local reads because descriptions tolerate temporary staleness. Keep the stronger path available for workflows that need it.

A fixed delay after writing is not proof that replication has caught up. If the requirement is only seeing your own edit, build on Read-your-writes consistency instead of promising global freshness.

Change the choice when an old value can cause harm, or when the remote path fits the latency budget comfortably.

For the catalog read/write interface, local stale reads favor EL. Its partition behavior depends on writes too. If description writes still require A, the interface does not provide CAP availability everywhere.

That is why “local reads” alone cannot justify labeling a whole database PA/EL.

Turn labels into operating rules

Use PACELC as two questions, not a database shopping category. Settings, routing and the operation contract determine the answer.

For each important operation, record:

  1. What completed work must this request observe?
  2. Which component can authorize its result?
  3. What happens when that component cannot be reached?
  4. Which communication steps are on the healthy request path?
  5. What must happen before normal routing resumes?

These questions expose choices that “strong” or “available” alone leave unspecified.

For Kartly, set a bounded wait on forwarded reservations. When it expires, return a temporary failure or an unknown-outcome response, depending on whether submission may have reached A. Never fall back to locally confirming stock.

A timeout is a policy trigger, not proof that the remote node is dead. Brewer connects this practical timeout decision to the consistency–availability choice.2

Monitor reservation failures separately from catalog latency. Also track replication progress and unresolved reservation attempts. Otherwise a healthy browsing dashboard could hide a checkout outage.

Where this shows up

Our fixed authority makes the tradeoff visible; next, Quorums asks which replica responses can safely authorize progress.

Common mistakes

  • Treating a fast error as availability. A temporary error protects the stock contract, but the reservation operation did not complete.
  • Equating convergence with correctness. Matching counts after repair do not erase two incompatible customer confirmations.
  • Inferring consistency from synchronous copying alone. Read routing and safe authority transfer must also preserve the promised ordering.
  • Using one label for every endpoint. An approximate description and a final stock reservation have different acceptable outcomes.
  • Treating latency estimates as guarantees. Our arithmetic excludes contention, variable network delay and storage stalls.

Check your understanding

Check yourselfAnswer in your head first, then reveal
A confirms remaining stock changed from 1 to 0. After confirmation, B returns 1 during a partition. Nobody writes at B. Did the stock interface preserve CAP consistency?Show answerHide answer
No. Linearizability applies to reads too, and this read followed a completed write. Having only one writer does not make an old replica read current.
Check yourselfAnswer in your head first, then reveal
B returns 503 immediately when it cannot reach A. Has the service preserved CAP availability because every request received an HTTP response?Show answerHide answer
No. The requested stock operation must complete, not merely receive a transport-level reply. The error is an intentional loss of availability to protect the operation’s contract.
Check yourselfAnswer in your head first, then reveal
A catalog uses local stale reads during healthy operation, but every write requires A. Can you conclude that it provides availability during every partition?Show answerHide answer
No. An isolated B cannot complete writes under that policy. Healthy-read latency and partition-time availability are separate questions.
Check yourselfAnswer in your head first, then reveal
The remote round trip falls from 80 ms to 20 ms. What happens to the illustrative authority-read total, and does that remove the CAP tradeoff?Show answerHide answer
The total becomes 32 ms: 12 ms plus 20 ms. It makes the healthy path cheaper, but a broken link still prevents the required remote answer.
Check yourselfAnswer in your head first, then reveal
After a partition, two replicas both show zero remaining stock. Is that enough to conclude that no overselling occurred?Show answerHide answer
No. Both might have independently reserved the same final unit. Inspect reservation histories and customer commitments, not just matching final counts.

Summary

  1. Wait or refuse when an operation needs unreachable authoritative information; answer locally only under a contract that permits it.
  2. CAP rules out guaranteeing linearizability and completion everywhere during a partition.
  3. Choose behavior per operation: approximate browsing and confirmed reservations need different promises.
  4. PACELC separates partition-time availability–consistency choices from healthy-operation latency–consistency choices.
  5. Define timeouts, retry identity and recovery behavior; a label alone does not specify a working system.

Report a mistake

Tell us what’s wrong in this lesson and we’ll fix it.