PACELC Theorem
CAP extended — if Partition (P), trade off Availability (A) vs Consistency (C); Else (E), trade off Latency (L) vs Consistency (C).
Intent & Description
🎯 Intent
Extend CAP theorem to handle normal operation trade-offs, not just failure scenarios. PACELC says: in case of Partition (P), choose between Availability (A) and Consistency (C); Else (E), when running normally, choose between Latency (L) and Consistency (C).
📋 Context
CAP only addresses what happens during network failures. But in normal operation, you still face trade-offs. Strong consistency requires synchronous replication, which adds latency. Eventual consistency allows asynchronous replication, reducing latency but risking stale reads. PACELC captures both failure-time and run-time trade-offs.
💡 Solution
Design your system for both scenarios. During partitions, decide AP vs. CP based on business requirements. During normal operation, decide EL vs. EC based on latency tolerance. Many systems choose EL (low latency, eventual consistency) for most operations, with EC paths for critical operations requiring strong consistency.
Real-world Use Case
📌 TL;DR
PACELC extends CAP: during partitions, choose AP vs. CP; during normal operation, choose EL vs. EC. More realistic for production systems where latency matters even when everything works.
Advantages
- More complete than CAP — addresses both failure and normal operation scenarios
- Realistic for production systems — latency matters even when everything works
- Guides system design for both happy path and failure scenarios
- Helps explain why “eventually consistent” systems can still have latency issues
Disadvantages
- More complex mental model than simple CAP — four combinations instead of two
- Still binary in each dimension — real systems have tunable consistency levels
- Does not address throughput trade-offs, only latency vs. consistency
- Less widely known than CAP — harder to communicate with stakeholders
// PACELC in practice: Different paths for partition vs. normal operation
class PACELCDatabase {
async write(key, value, consistency = 'eventual') {
if (this.isPartitioned()) {
// Partition mode: PAC — Availability vs. Consistency
if (consistency === 'strong') {
throw new Error("Unavailable: partition mode, cannot ensure consistency");
}
// AP: Write locally, replicate asynchronously
this.writeToLocal(key, value);
this.replicateAsync(key, value);
} else {
// Normal mode: ELC — Latency vs. Consistency
if (consistency === 'strong') {
// EC: Synchronous replication, higher latency
await this.replicateSync(key, value);
} else {
// EL: Asynchronous replication, lower latency
this.writeToLocal(key, value);
this.replicateAsync(key, value);
}
}
}
async read(key, consistency = 'eventual') {
if (this.isPartitioned()) {
if (consistency === 'strong') {
throw new Error("Unavailable: partition mode, cannot ensure consistency");
}
return this.readFromLocal(key); // May be stale
} else {
if (consistency === 'strong') {
return await this.readFromQuorum(key); // EC: Higher latency
} else {
return this.readFromLocal(key); // EL: Lower latency
}
}
}
}
// Usage examples
await db.write('user:123', data, 'strong'); // EC path
await db.write('feed:456', post, 'eventual'); // EL path