Introduction
In our last lesson, we contrasted Bigtable and Spanner, highlighting Spanner's ability to provide globally distributed, externally consistent ACID transactions. This powerful capability, which simplifies application development immensely, relies on sophisticated coordination protocols. To truly appreciate how systems like Spanner operate, we must first understand the foundational algorithms for achieving transactional atomicity in a distributed environment.
This lesson begins our exploration of advanced distributed transactions by analyzing the classic Two-Phase Commit (2PC) protocol. We will dissect its mechanics, identify its most significant drawback—its "blocking" nature—and examine the common failure modes that can impact a system's reliability. For an engineer aspiring to a Principal-level role, a firm grasp of 2PC is non-negotiable; it's the baseline against which more advanced protocols are measured and provides critical context for countless system design trade-offs.
The Atomic Commitment Problem
Before diving into the protocol itself, let's solidify the problem it aims to solve. Your experience with sharded databases provides a perfect starting point. When a single logical operation, like transferring funds or updating a user profile and their associated index, needs to modify data on multiple, independent nodes (or partitions), we face a challenge. If one node succeeds in writing its change but another fails, the database is left in an inconsistent state.
The goal is atomic commitment: the transaction must either successfully complete on all participating nodes (commit) or be rolled back on all nodes (abort), leaving the system as if the transaction never happened. There can be no middle ground.
The following video provides an excellent overview of the atomic commitment problem and distinguishes it from the general consensus problem we discussed in an earlier module.
Distributed Systems 7.1: Two-phase commit
In this video from his "Distributed Systems" series, Martin Kleppmann introduces the concept of atomic commitment.
Please watch the segment from the beginning of the distributed transactions section. Pay close attention to how he defines atomicity in a distributed context and why this problem is more constrained than general consensus.
The Mechanics of 2PC
Two-Phase Commit coordinates a transaction among a group of nodes. The protocol involves two types of actors: a single Coordinator and one or more Participants (sometimes called cohorts).
As its name implies, the protocol unfolds in two distinct phases, as illustrated in the diagram below.

Let's walk through the message flow.
Phase 1: The Prepare (or Voting) Phase
- Client Initiates: A client application initiates a transaction and performs reads and writes across multiple participants. When it's ready to commit, it sends a request to the coordinator, not the participants directly.
- Coordinator Sends
PREPARE: The coordinator sends aPREPAREmessage to every participant involved in the transaction. - Participants Vote: Upon receiving
PREPARE, each participant determines if it can guarantee the transaction's success.- To vote "yes," a participant must be certain it can commit. This involves performing all necessary validation and, crucially, durably logging its changes (e.g., to a write-ahead log) and any required locks. It then responds to the coordinator with a
VOTE-COMMIT. At this point, the participant is in a prepared state and has given up its right to unilaterally abort the transaction. - If a participant cannot commit for any reason (e.g., constraint violation, disk full), it can immediately respond with a
VOTE-ABORT.
- To vote "yes," a participant must be certain it can commit. This involves performing all necessary validation and, crucially, durably logging its changes (e.g., to a write-ahead log) and any required locks. It then responds to the coordinator with a
Phase 2: The Commit (or Decision) Phase
- Coordinator Decides: The coordinator collects votes from all participants.
- If all participants send
VOTE-COMMIT, the coordinator makes the final decision toCOMMIT. It durably logs this decision and then sends aCOMMITmessage to all participants. - If any participant sends
VOTE-ABORT, or if any participant times out, the coordinator decides toABORT. It logs this decision and sends anABORTmessage to all participants.
- If all participants send
- Participants Execute: Participants receive the final decision from the coordinator. They execute the command (commit or abort), release any locks they were holding for the transaction, and send an
ACKmessage back to the coordinator. - Coordinator Completes: The coordinator waits to receive an
ACKfrom every participant. Only then can it garbage collect the transaction information and consider the process complete.
To see this flow in action, the following video offers a clear, step-by-step walkthrough.
Two Phase Commit - Distributed Transactions | Systems Design Interview 0 to 1 with Ex-Google SWE
This video provides a whiteboard-style explanation of the 2PC protocol flow.
Watch the segment explaining how 2PC works. This visualization will help solidify your understanding of the message exchange and the role of the coordinator's log.
The Blocking Nature of 2PC
The protocol seems straightforward, but its primary weakness lies in what happens when failures occur at inopportune moments. The most significant issue is its blocking nature.
A participant is blocked if it enters the "prepared" state but does not receive a final COMMIT or ABORT decision from the coordinator. This happens if the coordinator crashes or a network partition separates the participant from the coordinator.
Why is this so problematic?
- A prepared participant cannot make a unilateral decision. It can't abort, because the coordinator might have already decided to commit and told other participants to do so. It can't commit, because another participant might have voted to abort, causing the coordinator to decide to abort.
- The participant is stuck in an uncertain state and must wait for the coordinator to recover and provide the final decision.
- While blocked, the participant must continue to hold locks on the data involved in the transaction. These locks prevent other transactions from proceeding, potentially causing a significant drop in system availability that can cascade through the application.
This blocking property is the most criticized aspect of 2PC and a major reason why system designers often seek alternatives.
Distributed Systems 7.1: Two-phase commit
Martin Kleppmann's video continues with a precise analysis of what happens when the coordinator fails.
Watch the segment that covers coordinator failure. This section masterfully explains how coordinator failure leads to the blocking condition in participants.
Analyzing Failure Modes
To build robust systems, you must be able to reason about failure scenarios. Let's analyze the key failure modes in 2PC.
Participant Failure
- Failure before voting: If a participant crashes before responding to the
PREPAREmessage, the coordinator will time out and decide toABORTthe entire transaction. This is a safe outcome. - Failure after voting
VOTE-COMMIT: This is the problematic case. When the participant recovers, it will find its "prepared" status in its log. It is now in the uncertain, blocked state. It must repeatedly contact the coordinator to find out the transaction's final outcome. If the coordinator is also down, the participant remains blocked indefinitely.
Coordinator Failure
The impact of a coordinator failure depends entirely on the timing.
- Failure before sending
PREPAREmessages: The transaction effectively never started. No participants are prepared, so no blocking occurs. - Failure after sending
PREPAREbut before logging a final decision: Upon recovery, the coordinator can see from its log that it started the protocol but never reached a decision. It can safely decide toABORTthe transaction and notify participants. - Failure after logging a decision but before sending it to all participants: This is the most common cause of blocking. Upon recovery, the coordinator reads its log, finds the decision, and resumes sending it to any participants that have not yet acknowledged it. The system eventually becomes consistent, but participants were blocked for the duration of the coordinator's outage.
- Catastrophic Failure (Coordinator log is lost): This is a disaster scenario. If the coordinator loses its durable log of the decision, the system may never be able to resolve the transaction's outcome. Some participants might have received a
COMMITand released their locks, while others are still blocked and holding locks. This can lead to permanent inconsistency, violating the atomicity guarantee that 2PC was designed to provide.
The following paper is a canonical source on 2PC and its optimizations. We'll use it to formalize our understanding of recovery.
A New Presumed Commit Optimization for Two Phase ...
This paper by Lampson and Lomet provides a detailed description of the basic 2PC protocol, including the logging and recovery actions required of both coordinators and participants (cohorts).
Please read the subsection "Cohort Activity" (2.2), focusing on the paragraph that explicitly mentions the protocol's main weakness. It starts with "If a prepared cohort...". This text formally describes the blocking problem from the participant's perspective.
The image below illustrates a subtle but critical failure scenario. After participant X and coordinator C2 have failed, two possible prior executions (W1 and W2) are indistinguishable to a recovering participant Y. In W1, the transaction was on a path to commit. In W2, it was on a path to abort. Since Y cannot distinguish between these pasts, it has no choice but to block until it can learn the true outcome from a recovered coordinator.

Beyond just blocking, modern distributed systems design, especially in multi-tenant cloud environments, exposes another concern with 2PC: trust and resource exhaustion. A malicious participant could vote to commit and then intentionally never release its locks, or a malicious coordinator could intentionally "hang" transactions. This makes 2PC a difficult fit for environments where participants don't fully trust each other.
Conclusion
In this lesson, we have dissected the Two-Phase Commit protocol, a foundational algorithm for atomic commitment in distributed systems. While it provides the crucial guarantee of atomicity, its architectural trade-offs are severe and must be understood deeply.
Here are the key takeaways:
- Protocol: 2PC uses a coordinator to orchestrate a two-phase process: a voting phase where participants promise to commit, and a decision phase where the final outcome is broadcast.
- Atomicity: It guarantees that a transaction spanning multiple nodes will either commit on all nodes or abort on all nodes, preventing inconsistent states.
- Blocking: Its most significant flaw is that participants can become blocked if the coordinator fails after they have entered the prepared state. A blocked participant holds locks and is unavailable until the coordinator recovers.
- Single Point of Failure: The coordinator is a performance bottleneck and a single point of failure. Its failure can halt transaction processing, and the loss of its state can lead to catastrophic data inconsistency.
Understanding the limitations of 2PC is what drives the search for better solutions. Your experience designing systems with sharding likely gave you an intuitive sense of why cross-partition atomic operations are difficult; 2PC formalizes the challenges.
In our next lesson, we will build directly on this foundation. We'll compare 2PC with more advanced and resilient alternatives, such as Paxos Commit and the SAGA pattern. These approaches were designed specifically to mitigate the blocking problem and single point of failure inherent in classic 2PC, offering different trade-offs in the quest for reliable distributed transactions.