Two-phase commit is a coordinator-driven protocol that gets every participating database to agree before any of them commits, which is exactly how it guarantees atomicity across nodes that cannot see each other's internal state. That guarantee comes from holding a lock open across a network round trip, and that single design choice is why most teams building services across independently deployed systems have moved away from it. The protocol is not wrong, it is narrower than it used to be treated: it fits cleanly inside one trust boundary and gets risky the moment it crosses one.
How it works
Picture a transfer that must debit an account balance in one database and decrement a warehouse reservation count in another. Two-phase commit runs it in two rounds:
- Prepare phase. The coordinator asks both participants to get ready. Each one does the work, writes it to a durable log, but withholds the actual commit, and replies ready or not ready.
- Commit phase. Only if both replied ready does the coordinator tell both to finalize the change. If either refused or timed out, the coordinator tells both to abort instead.
The property this buys is atomicity: either both sides apply the change, or neither does. What it does not buy is availability during a failure, and that tradeoff is the entire story of the protocol.
Why it gets avoided
The failure mode is specific. A participant that already replied "ready" has made a promise it cannot break on its own: it cannot unilaterally commit, and it cannot unilaterally abort, so if the coordinator crashes before sending the final instruction, that participant sits holding its locks, blocking any other transaction that touches the same data, until the coordinator recovers or an operator steps in by hand.
Across services owned by one team on reliable internal infrastructure, that risk is manageable. Across an organizational boundary, it stops being purely technical: nobody wants their service to freeze because another team's system is having a slow afternoon, and that coupling defeats much of the reason the services were split apart in the first place. Three-phase commit attempts to fix the blocking window with an extra round trip, but it is rarely used in practice, since it still fails under a genuine network partition.
When it still makes sense
| Situation |
Fit for 2PC |
| Participants are internal nodes of one database engine |
Good — close to the protocol's original design point |
| Participants are a few services on one team's infrastructure |
Usable, but risky under real load |
| Participants cross a team or company boundary |
Avoid — prefer compensating steps or eventual consistency |
| Strong same-instant consistency is a hard legal or financial requirement |
Sometimes the least-bad option, after shrinking the participant set as far as possible |
Common mistakes
- Treating 2PC as free correctness. It buys atomicity at the direct cost of availability during a failure; that trade needs an explicit owner, not a default assumption.
- Not monitoring in-doubt transactions. Without alerting on stuck prepare states, a coordinator crash becomes a silent, spreading lock problem instead of a fast, visible incident.
- Applying it across an organizational boundary. You cannot make another team hold a lock open for your convenience, and pretending otherwise just delays the outage.
- Skipping the recovery design. A 2PC deployment with no clear path for a crashed coordinator is a liability waiting for the wrong kind of day.
FAQ
Is two-phase commit ever the right call in 2026?
Yes, narrowly, for a small, fully-owned set of participants where strong atomicity genuinely matters more than availability.
What actually happens to a stuck participant?
It holds its prepared state and any associated locks until the coordinator resolves the transaction, or until an operator intervenes manually.
Why do microservice teams avoid it instead of just using it everywhere?
Because it couples the availability of services that were split apart specifically to avoid that kind of coupling.
Does adding more participants make the risk worse?
Yes. The odds that at least one participant is slow or unavailable rise with every additional participant, and a blocking protocol punishes that linearly.
Where to go next
Read distributed transactions in microservices for the full option space this protocol sits inside, the outbox pattern explained for the safer default most teams reach for instead, and what a merge conflict is for another case where two changes cannot both be true at once.