I use two phase commit as the example of paying coordination cost for all or nothing behavior. I recommend it only when partial success is worse than slower commits and blocking risk.
Prepare first, commit second
When I talk about "Prepare first, commit second", I am really asking what Two Phase Commit does when a message is late, duplicated, or missing.
In phase one, the coordinator asks each participant to prepare. A prepared participant records enough information to commit later. In phase two, the coordinator tells everyone to commit or roll back.
Reservation example
I use "Reservation example" to keep Two Phase Commit grounded in a real system, because abstract patterns are too easy to agree with and too hard to operate.
An order workflow needs inventory and payment to succeed together. If payment prepares but inventory cannot prepare, the coordinator rolls the transaction back.
Coordinator code
When I show "Coordinator code", I want the code in Two Phase Commit to reveal the production decision, not just the syntax.
Prepare every participant before sending the final commit:
if (payment.prepare(xid) && inventory.prepare(xid)) {
payment.commit(xid);
inventory.commit(xid);
} else {
payment.rollback(xid);
inventory.rollback(xid);
}
The coordinator commits only when both participants prepare successfully. If either side cannot prepare, both roll back so the transaction does not split.
Sequence diagram: prepare before commit
The final commit only happens after every participant promises it can finish.
The atomicity choice
- Use it when partial success is more expensive than coordination.
- Plan for coordinator failure and participant recovery.
- Avoid it for high volume loose workflows where events and compensation are enough.