Three-Phase Commit: Why It Exists and Why Nobody Uses It
December 24, 2025
Three-phase commit is one of those protocols every distributed systems class teaches and almost no production system runs. The reason is more interesting than the protocol.
Start with the problem 3PC tries to solve. In two-phase commit, the coordinator asks every participant to vote, collects the votes, then sends a commit or abort decision. The flaw is the window after voting yes. A participant that votes yes is now in a PREPARED state, holding locks, waiting to be told what happens next. If the coordinator crashes at that moment, the participant has no way to decide on its own. It cannot commit, because some other participant might have voted no. It cannot abort, because the coordinator might have already committed somewhere else. It holds the locks and waits, possibly forever. That is the blocking problem.
Three-phase commit adds a step in the middle to remove the ambiguity.
- CanCommit. The coordinator asks each participant whether it is able to commit. Participants answer yes or no but do not yet lock anything terminally.
- PreCommit. If all yes, the coordinator sends a PreCommit message. This is the key idea. A PreCommit tells every participant that the global decision is now commit. There is no longer a state where some saw yes and others saw no.
- DoCommit. Participants finalize.
The win is what happens when the coordinator dies after PreCommit. Each participant already knows the decision was commit, because PreCommit reached them. They can elect a new coordinator, exchange state, and finish on their own. No indefinite wait.
In theory, you have a non-blocking atomic commit protocol. In practice, no one ships it. Here is the actual reason.
3PC assumes a synchronous network with bounded message delays and no partitions. The participant logic depends on detecting coordinator failure via timeout: if I do not hear back in T, the coordinator is dead, recovery starts. That works only if message delays are guaranteed to be less than T. On a real network, messages can be arbitrarily delayed by a partition, a long GC pause, a saturated link, a misbehaving switch. A delayed message looks identical to a dead coordinator. Two halves of a partition can each decide differently. You lose atomicity, which was the entire point.
The FLP impossibility result formalizes this: in an asynchronous network with even one faulty node, no deterministic protocol can guarantee consensus. 3PC does not escape that. It only works inside the asynchronous-but-bounded model, which datacenters approximate sometimes and the internet never does.
That is why modern systems went a different direction. Raft and Paxos accept asynchrony and use leader election plus quorum to make progress. Sagas drop atomicity entirely and use compensation. 3PC sits in textbooks, taught for the same reason we teach bubble sort: it explains the next idea.
3PC is non-blocking, but only on a synchronous network with bounded delays and no partitions. Real networks do not behave that way, which is why Raft and sagas won instead.
Originally posted on LinkedIn. View original.