Glossary Distributed Systems

Two-Phase Commit

A distributed coordination protocol that ensures all participants in a transaction either commit or abort atomically, using a prepare phase followed by a commit phase.

The Distributed Transaction Problem

A single database transaction is atomic: either all changes commit or none do. Distributed systems break this guarantee. Consider an e-commerce checkout that must debit a customer account in one database and create an order record in a second database. If the debit succeeds and then the order creation fails, the customer has been charged for an order that does not exist. If you reverse the order: the order exists but the charge never happened. There is no atomic commit across two independent databases without a coordination protocol.

Two-phase commit (2PC) is the classical solution. It adds a coordinator that orchestrates all participants to agree on a single outcome before any of them commit.

Phase 1: Prepare

The coordinator sends a Prepare message to every participant. Each participant must decide: can I commit this transaction? The participant writes the transaction data to its transaction log, acquires all necessary locks, and responds with either a Yes vote or an Abort vote. Critically, a Yes vote is a promise: the participant is guaranteeing it can commit regardless of what happens to the coordinator after this point.

Phase 2: Commit or Abort

If all participants voted Yes, the coordinator writes a Commit record to its own log and sends Commit to all participants. Each participant commits, releases locks, and acknowledges. If any participant voted Abort (or timed out), the coordinator writes an Abort record and sends Abort to all participants. Each participant rolls back.

The two-log-write sequence (coordinator first, then participants) is essential for recovery. If the coordinator crashes after writing Commit to its log but before all participants receive the message, the recovered coordinator can re-send Commit by reading its log.

The Blocking Problem

2PC has a critical flaw: if the coordinator crashes after Phase 1 (after participants have voted Yes but before the coordinator has sent Phase 2), participants are stuck. They have locked resources and cannot decide unilaterally whether to commit or abort. They must wait for the coordinator to recover. During this window, those locks are held, and any transaction touching the same rows is blocked.

This is not a hypothetical failure mode. Coordinator crashes happen. In a system with thousands of concurrent transactions, even a brief coordinator outage creates a lock-holding standoff that cascades into timeouts across the system.

XA Protocol

XA is the standard interface that defines how a transaction manager (coordinator) communicates with resource managers (participants, such as databases). Most enterprise databases support XA. Java's JTA (Java Transaction API) uses XA. The protocol works correctly, but the blocking problem and the performance cost of holding locks across two network round trips make it impractical for high-throughput systems.

Three-Phase Commit

3PC was designed to address 2PC's blocking problem by adding a pre-commit phase between prepare and commit. In theory, if the coordinator crashes after pre-commit, participants can detect this and coordinate a decision among themselves. In practice, 3PC requires synchronous messaging with tight timeouts and is still vulnerable to network partitions where some participants receive the pre-commit and others do not. It adds a full extra round trip of latency. Almost no production systems use 3PC. It solves a theoretical problem at a practical cost that makes the alternatives (Saga, eventual consistency) more attractive.

Why Modern Distributed Systems Avoid It

At the latency of two network round trips plus lock-holding time, 2PC typically adds 10-100ms per transaction depending on participant geography. Combined with the blocking failure mode, most modern distributed systems reject 2PC in favor of: the Saga pattern (compensating transactions), eventual consistency with application-level conflict resolution, or single-leader designs that avoid the distributed transaction problem entirely. Google Spanner uses a form of 2PC with TrueTime to bound clock uncertainty, but it is co-located in the same datacenter rack and the coordinator crashes are handled differently than in a WAN deployment.

Interview Tip

The coordinator crash scenario is the probe. 80% of candidates describe the two phases correctly. The question that separates them: "What happens if the coordinator crashes after all participants have voted Yes but before sending Phase 2?" The correct answer: participants are blocked indefinitely holding locks. They cannot commit (they do not know if all others voted Yes) and they cannot abort (they promised to commit if asked). This is the fundamental unsolvability of 2PC without external intervention, and the reason 3PC was proposed but ultimately not adopted at scale. L5+ candidates connect this to why the Saga pattern exists and what consistency model it provides instead.