Distributed Transactions: Why 2PC Fails at Scale
Spring Boot Mastery's @Transactional works because one database can guarantee atomicity by itself. Once a business operation spans multiple SERVICES, each with its own database, that guarantee quietly disappears — this module is why, precisely.
Learning objectives
- Beginner: Explain why @Transactional alone can't keep two different services' databases consistent.
- Intermediate: Describe how Two-Phase Commit (2PC) attempts to solve this, and name its coordinator's two phases.
- Advanced: Explain why 2PC is rarely used in real microservices systems despite solving the theoretical problem.
◆ The problem
Placing an order needs to both create a row in order-service's database AND decrement stock in inventory-service's COMPLETELY SEPARATE database. @Transactional guarantees atomicity within ONE database connection — it has no mechanism at all for guaranteeing that a write in one service's database and a write in another service's database either both happen or neither does.
If the order gets created but the stock decrement call fails (network blip, inventory-service briefly down), you've now sold a product with no stock reserved for it — a real, visible business bug, not a theoretical one.
2PC introduces a coordinator that asks every participating database, in a PREPARE phase, "can you commit this if I ask?" — each replies yes/no without actually committing yet. Only if EVERY participant says yes does the coordinator send a COMMIT phase telling all of them to actually finalize; if even one said no, it tells all of them to abort instead.
| Phase | What happens |
|---|---|
| Prepare | Coordinator asks every participant to lock resources and confirm it COULD commit. |
| Commit (or Abort) | Only if all participants agreed — coordinator tells everyone to finalize (or roll back) together. |
⚠ Common real-world trap
2PC requires every participant to hold locks on its resources from the Prepare phase until the Commit phase completes — if the coordinator itself crashes in between, participants can be left holding locks INDEFINITELY, blocking unrelated operations on the same data. It also requires every participating database to support the same distributed-transaction protocol, which most NoSQL stores and message brokers (including Kafka) simply don't.
This is precisely why real microservices systems reach for the Saga pattern (next module) instead — trading strict, all-or-nothing atomicity for a sequence of local transactions plus explicit compensating actions if something downstream fails.
Why Spring Cloud's own toolset doesn't offer 2PC
Spring does technically support XA (the standard 2PC protocol) via JtaTransactionManager combined with an XA transaction manager like Atomikos or Bitronix — but you'll rarely see this in a real Spring Cloud microservices codebase, and it's worth knowing why: XA requires an XA-compliant JDBC driver AND an XA-compliant message broker on every participant, which immediately rules out Kafka (this course's own default choice for event-driven communication) and most NoSQL stores. Spring Cloud's actual toolset — Spring Cloud Stream for choreography, plain Spring beans for orchestration — is built around the Saga pattern instead, not because XA is unsupported on the JVM, but because it doesn't fit the technology choices the rest of the ecosystem already made.
✓ Quick recap
- @Transactional guarantees atomicity within one database — it has no answer for a business operation spanning multiple services' separate databases.
- 2PC's coordinator uses a Prepare-then-Commit protocol to attempt all-or-nothing atomicity across multiple databases.
- 2PC's locks-held-across-two-phases design creates real availability risk if the coordinator itself fails, and most modern data stores don't even support the protocol — which is why it's rarely used in practice despite being theoretically correct.
- Spring does have XA support (
JtaTransactionManager+ Atomikos/Bitronix), but it requires XA-compliant participants everywhere, which rules out Kafka — exactly why Spring Cloud's own tooling is built around Saga instead.
Want a visual for this concept?
Generate a diagram tailored to “Distributed Transactions: Why 2PC Fails at Scale” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.
Sign in to generate a visual →