The Problem Traditional Transaction Models
A single-node database can promise all-or-nothing cheaply because one lock manager guards every row and one write-ahead log (WAL) sits behind every write, so a whole transaction commits with a single fsync of one commit record; the moment you split those rows across an order service, an inventory service, and a payment service on three different machines, that shared log and shared lock manager are gone, and the only way to keep atomicity is a coordinator that forces every node to first promise it can commit and then commit in lockstep — a protocol called two-phase commit (2PC), whose promise step is exactly what wedges the system when a machine dies.
Why ACID is easy on one node
ACID is not four unrelated features; on a single node it is mostly one mechanism reused four ways. Atomicity and Durability come from the WAL: the transaction's changes are appended to the log, and a single durable commit record flips the whole transaction from "nothing happened" to "everything happened." Isolation comes from the lock manager (or MVCC snapshots) inside the same process, which sequences concurrent transactions as if they ran one at a time. Consistency is the invariant those three preserve — the database only ever moves from one valid state to another. Because a single log and a single lock manager arbitrate everything, "commit" is one local, ordered, durable act.
Distribute the data and every one of those crutches disappears: there is no shared log to append a single commit record to, and no shared lock manager to serialize contenders. Atomicity now requires that three independent databases, reachable only over a flaky network, all flip together — or none do.
The concrete mechanism that tries — and blocks: 2PC
Two-phase commit introduces a coordinator (a transaction manager) and treats each service's database as a participant (resource manager). It runs in two rounds:
- Phase 1 — Prepare (voting): the coordinator asks every participant "can you commit?" Each participant does the work, writes a durable prepare record, locks the affected rows, and replies
YES(I am prepared and will commit if told to) orNO. - Phase 2 — Commit/Abort: if all votes are
YES, the coordinator writes its own durableCOMMITrecord — the atomic point of no return — and tells everyone to commit and release locks. AnyNO(or timeout) turns into a globalABORT.
The trap lives between the phases. Once a participant has voted YES it is in-doubt: it is holding locks and has promised it can commit, so it must not unilaterally commit (the decision might be abort) and must not unilaterally abort (the decision might be commit). It can only wait for the coordinator.
Worked trace: checkout for order #7788, total $85
The coordinator is the checkout orchestrator; the three participants each own their own database. First the happy path succeeds atomically:
| Step | t | Actor | Action | Resulting state |
|---|---|---|---|---|
| 1 | 0 ms | Coordinator | Writes BEGIN to its log; sends PREPARE to all three | Txn open |
| 2 | 15 ms | Inventory | Reserves SKU-42 (stock 10 → 9), locks the row, logs prepare | YES — row locked |
| 3 | 20 ms | Order | Inserts order #7788 status=PENDING, locks row, logs prepare | YES — row locked |
| 4 | 40 ms | Payment | Places an $85 authorization hold, logs prepare (cross-region hop) | YES — funds held |
| 5 | 45 ms | Coordinator | All votes YES → writes COMMIT to its log (atomic commit point) | Decision durable |
| 6 | 60 ms | All three | Receive COMMIT, apply, release locks, ack | Committed — atomic |
Now change one thing: the coordinator crashes at ~45 ms, after collecting all three YES votes but before the decision reaches anyone (or its decision log is lost). Every participant is prepared and in-doubt. Inventory still holds the lock on SKU-42; Payment still holds the $85 authorization; Order's PENDING row is locked. None of them may proceed. The SKU-42 row stays locked, so every other checkout touching SKU-42 now blocks behind it. Nothing frees until the coordinator reboots and replays its log — and if that log is gone, an operator must manually resolve the in-doubt transaction. That indefinite freeze is the blocking problem, and it is inherent: no atomic-commit protocol can be non-blocking when both the network and nodes can fail.
Pitfalls
- Coordinator is a single point of failure that blocks, not just fails. A coordinator crash between phases freezes every prepared participant; the locked rows stay locked until it recovers, and hot rows (a popular SKU) turn one stuck transaction into a site-wide stall.
- Locks are held for the full network round trip. On one node a lock lives microseconds; in 2PC it is held across two RTTs plus the slowest participant's work (40 ms above). Under load this collapses throughput and breeds distributed deadlocks.
- Heuristic decisions corrupt data silently. When a participant's own timeout fires, some XA resource managers make a heuristic commit or abort to release locks. If it guesses opposite to the coordinator, you get a partially committed transaction — money moved but no order — that a human must reconcile.
- In-doubt / prepared transactions pin the database. In Postgres or Oracle a forgotten prepared transaction holds locks and blocks vacuum/GC; one leaked
PREPARE TRANSACTIONcan wedge an entire instance. - Many resources cannot enlist at all. XA needs a resource manager that supports prepare/commit. Most external HTTP APIs, payment gateways, and many NoSQL stores simply cannot vote — so 2PC is not even an option, not just a slow one.
When to use 2PC — and when to reach for a Saga instead
2PC is the right tool when you genuinely need immediate, isolated atomicity across a small, closed set of XA-capable resources inside one latency and trust domain — e.g., two databases plus a message broker in the same datacenter, low write volume, short transactions, and a correctness requirement that outranks availability. You gain true all-or-nothing with isolation (no one sees intermediate states). You pay for it with synchronous blocking, cross-network locks, a coordinator SPOF, throughput that falls off a cliff under contention, and unavailability during a network partition (2PC is firmly CP).
Prefer the Saga pattern when the participants are independently-owned services, transactions are long-lived, throughput is high, or you must stay available during partial failure. A Saga runs the checkout as a sequence of local transactions, each committing immediately, with an explicit compensating action (cancel the reservation, void the authorization) to undo earlier steps on failure. The cost is real: you lose isolation — other requests can observe the half-done state — and you must design and test semantic rollbacks by hand. A middle option, 3PC, adds a round trip to reduce blocking but still blocks under network partitions, so it is rarely used in practice.
Choose 2PC when a couple of XA resources must be atomically consistent, volume is low, and a brief blocking window is acceptable. Prefer a Saga when services are autonomous, transactions span teams or time, and you can trade strict isolation and immediacy for availability and scale. And before either — if the data really must be atomic and consistent together, ask whether those services should share one database at all; collapsing them back is often the honest answer.
Takeaways
- ACID is cheap on one node because a single WAL and a single lock manager arbitrate every commit; distributing the data destroys that shared arbiter.
- 2PC restores atomicity by making participants prepare (lock + promise) before anyone commits — which is exactly why it blocks: a prepared node cannot move without the coordinator.
- Coordinator-as-SPOF, network-long lock holds, and the XA requirement make 2PC a poor fit for high-throughput, independently-owned microservices.
- The escape is to trade strict isolation and immediacy for availability — local transactions plus compensations, i.e. the Saga pattern the next lessons build.
Re-authored and deepened for this guide. Sources: Gray & Reuter, Transaction Processing: Concepts and Techniques (atomic commit, 2PC blocking); Bernstein & Newcomer, Principles of Transaction Processing (XA, heuristic decisions); Martin Kleppmann, Designing Data-Intensive Applications, ch. 9 (distributed transactions and the impossibility of non-blocking atomic commit); Chris Richardson, Microservices Patterns (why 2PC is avoided, the Saga alternative).
🤖 Don't fully get this? Learn it with Claude
Stuck on The Problem Traditional Transaction Models? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **The Problem Traditional Transaction Models** (System Design) and want to truly understand it. Explain The Problem Traditional Transaction Models from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **The Problem Traditional Transaction Models** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **The Problem Traditional Transaction Models** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **The Problem Traditional Transaction Models** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.