skip to content

A distributed transaction coordinator needs to make sure a payment write to Database A and an inventory write to Database B either both happen or neither happens. Walk through how the two-phase commit (2PC) protocol achieves this, phase by phase.

level: juniorimportance: must knowfreq 75%

answer

  1. prepare then commit
  2. vote-commit/vote-abort
  3. coordinator writes decision first
  4. locks held during prepare window
  5. XA / JTA standard

basics

~10 s

2PC asks everyone 'can you commit?' first (prepare phase). Only if all say yes does it tell them to actually commit (commit phase). If anyone says no, everyone rolls back.

solid answer

~40 s

Two-phase commit coordinates an atomic decision across multiple participants (databases, brokers, etc.) that each hold part of a transaction. In the prepare (voting) phase, the coordinator sends PREPARE to every participant; each does whatever work is needed to guarantee it CAN commit — writes its changes to a durable redo/undo log, acquires locks, and replies VOTE-COMMIT or VOTE-ABORT. If every participant votes COMMIT, the coordinator durably records the decision as COMMIT and sends COMMIT to all, who apply their changes and release locks. If any votes ABORT or times out, the coordinator records ABORT and everyone rolls back. The protocol guarantees all-or-nothing atomicity at the cost of participants holding locks and being blocked between the two phases.

go deeper

for a junior

Should describe the two phases in plain terms — ask everyone if they're ready, then tell everyone to go — and understand the goal is all-or-nothing across multiple databases.

for a middle

Should name the vote messages (VOTE-COMMIT/VOTE-ABORT, PREPARE/COMMIT), know that participants hold locks between phases, and know a real technology (XA/JTA) that implements it.

for a senior

Should articulate why the durable log writes happen where they do (participant before voting, coordinator before phase 2), and connect the protocol's cost — held locks, extra round trips — to why teams avoid it across service boundaries.

for a principal

Should reason about 2PC as a design choice with organizational and architectural consequences — when it's worth accepting the blocking/availability trade-off (e.g., within a single trusted cluster) versus pushing for Sagas or single-database transactions instead.

## The problem it solves **Two-phase commit (2PC)** is the classical protocol for making an atomic commit decision across multiple independent resource managers — separate databases, queues, or services — that each control a disjoint piece of a single logical transaction. The problem it solves is straightforward to state and hard to solve: if a transaction touches Database A and Database B, you need a guarantee that either both databases apply the change or neither does, even though the two databases have no shared memory and can fail independently at any instant, including mid-message. ## The two phases **Mechanism, step by step.** A dedicated **coordinator** process (sometimes a database acting in a coordinator role, sometimes a standalone transaction manager like an XA-compliant TM) drives the protocol in two phases. 1. **Phase 1 — Prepare/Vote:** the coordinator sends a `PREPARE` message to every participant. Each participant does all the work necessary to make commit possible without yet making it visible: it executes the local part of the transaction, writes redo/undo information to its own durable write-ahead log, and acquires whatever locks are needed to prevent conflicting access. It then replies `VOTE-COMMIT` if it is certain it can durably commit on request, or `VOTE-ABORT` if it hit any failure (constraint violation, deadlock, disk full). Once a participant votes COMMIT it has entered an 'uncertain'/'in-doubt' state: it must be able to honor a future COMMIT instruction no matter what happens to it in between, which is why the vote is backed by a durable log write before the message is sent. 2. **Phase 2 — Commit/Abort:** the coordinator collects all votes. If every participant voted COMMIT, the coordinator writes its own durable commit record — the single moment the outcome becomes fixed — and sends COMMIT to all participants, who apply their buffered changes and release locks. If any participant voted ABORT or failed to respond within a timeout, the coordinator writes an abort record and everyone undoes their prepared work. ## Why it exists 2PC exists because plain 'write to both and hope' cannot give atomicity: without coordination, one database could commit while the other crashes or rejects the write, leaving the two permanently inconsistent (money debited but inventory never decremented). 2PC turns that into a single, coordinator-owned decision point, sufficient to guarantee atomicity as long as messages eventually get delivered and participants eventually recover. ## What it costs **Trade-offs.** The cost is real and operational. 1. **First**, 2PC is a **blocking protocol**: once a participant votes COMMIT, it must hold its locks and keep the prepared state durable until it hears back, because the coordinator might have told other participants the opposite outcome. 2. **Second**, it adds at least two network round trips to every transaction, paid by every participant even for work only one of them cares about. 3. **Third**, all participants must support the protocol (XA drivers, compatible locking), ruling out plain HTTP calls to services that don't implement a prepare-style API. 4. **Fourth**, throughput suffers because locks are held across the round trip, not just local work, so 2PC scales poorly to high-latency or many-participant transactions — one reason it's rarely used across microservice boundaries. ## How it fails **Failure modes in production.** The signature failure is coordinator failure between phase 1 and phase 2 (the 'blocking problem'): a participant that voted COMMIT and lost contact with the coordinator cannot safely unblock itself, because it cannot tell whether the coordinator decided COMMIT or ABORT before it died. It must sit holding locks — an 'in-doubt' transaction — until the coordinator recovers, or an operator manually forces a 'heuristic' decision, risking inconsistency if the guess is wrong. Timeout tuning is also a real headache: - too short and you abort transactions that would have succeeded; - too long and you hold locks (blocking other transactions) for minutes. ## Where you meet it **Concrete usage.** XA transactions (the X/Open Distributed Transaction Processing standard) are the most common real-world instantiation: Java's JTA, most enterprise application servers, and databases like Oracle, PostgreSQL, and MySQL all support XA-style 2PC so a single transaction manager can coordinate commits across, say, an Oracle database and an IBM MQ queue in one logical transaction. It historically underpinned distributed relational database middleware before microservice architectures pushed most teams toward Sagas for cross-service consistency instead.

  • What must a participant durably log before it votes YES in the prepare phase, and why?
    It must write its redo/undo information and the fact that it voted YES to its own durable write-ahead log before replying. This is because once it votes YES, the coordinator may decide to commit, and the participant must be able to honor that decision even if it crashes and restarts immediately after voting — without the durable log it would have no way to know it had promised to commit.
  • Why does the coordinator's own commit-record write matter more than any individual participant's log entry?
    The coordinator's durable commit record is the single moment the transaction's outcome becomes irrevocably fixed — before that write it can still choose to abort; after it, the transaction is committed even if participants haven't been told yet. This makes the coordinator the sole source of truth for recovery: if it crashes and restarts, it reads that record to know exactly what to tell participants.
  • Does 2PC guarantee availability during a network partition?
    No. 2PC sacrifices availability for consistency: if the coordinator can't reach a participant during phase 2, or a participant can't reach the coordinator after voting, that participant blocks rather than making progress, so the transaction and its held locks stall until connectivity or the coordinator returns.

Like a wedding officiant asking both partners privately 'do you take this person' before either says 'I do' aloud — only once both privately confirm YES does the officiant announce it as final; if either says no, nothing is official.

saying these in an interview costs you the question

  • Says 2PC guarantees availability under partitions
  • Thinks participants can unilaterally abort after voting COMMIT
  • Confuses 'prepare' with 'commit' — thinks changes are visible after phase 1
  • Doesn't mention durable logging before voting
  • Claims 2PC has no performance cost

context