The Two-Phase Commit (2PC) Protocol: The Blocking Consensus That Everyone Uses Anyway

2026-08-31

You've probably heard 2PC dismissed as "the protocol that blocks forever if the coordinator dies." That's true. It's also still running inside XA transactions, Kafka's transactional producer, MySQL group replication, and every distributed database that promises atomic multi-shard writes. Worth understanding what it actually does before you reject it.

The protocol in two phases:

The blocking problem: If the coordinator crashes after collecting YES votes but before broadcasting the decision, participants are stuck. They can't abort — they promised to commit. They can't commit — they don't know if others voted YES. They hold locks until the coordinator recovers. This is why 2PC has a reputation for "wedging" clusters.

Real-world example — MySQL XA transactions across shards: Say you're moving $100 from account A on shard-1 to account B on shard-2. Without 2PC, a network blip after debiting A but before crediting B leaves money vanished. With 2PC: both shards prepare (debit/credit logged as pending, row locks held), then both commit atomically. If shard-2 says "disk full" during prepare, shard-1 aborts cleanly. The tradeoff: rows on both shards are locked for the full prepare-to-commit window — typically 10-50ms, but if the coordinator dies mid-flight, potentially hours until DBA intervention.

Rule of thumb for lock duration: Estimate P(coordinator failure during commit window) × mean_recovery_time. If your coordinator has 99.9% uptime and takes 4 hours to manually recover, and your commit window is 20ms, you're looking at roughly 0.001 × 4 hours × (20ms / total_time) — small in expectation, catastrophic when it hits. That's why 2PC works fine at low volume and destroys you at scale.

When to use 2PC: Cross-shard transactions where consistency matters more than availability, low-frequency operations (billing settlement, account merges), and systems with a highly available coordinator (Raft-replicated, not a single node). When to avoid it: Hot paths, microservices spanning teams, anywhere you'd prefer eventual consistency with a Saga.

Key Takeaway: 2PC gives you atomicity across nodes at the cost of blocking when the coordinator fails — acceptable for rare, high-value transactions with a resilient coordinator, disastrous for high-throughput hot paths.

All newsletters