LESSON 20.1
Dual writes and two-phase commit
Why writing to two systems is never atomic by accident, how two-phase commit makes it atomic, and why services rarely use it.
5 min read
Inside one database, a transaction makes several changes all-or-nothing. A business action like "place an order" often touches several services: orders, payments, inventory, and a message broker. No single database transaction covers them all.
The dual-write problem
Any code that writes to two systems in sequence has a gap:
- Write to the database. Succeeds.
- Crash, timeout or deploy.
- Publish the event, call the other service or update the cache. Never happens.
Reversing the order doesn't help; it just changes which side is left inconsistent. Retrying helps only if the process survives to retry. Every fix in this module is a way of closing that gap.
Two-phase commit
2PC makes several participants commit atomically, coordinated by one transaction manager.
- Prepare: each participant does the work, writes it durably and holds its locks, then votes yes or no.
- Commit: if every vote is yes, the coordinator logs the decision and tells everyone to commit. Any no means everyone aborts.
Why services avoid it
Two-phase commit
- True atomicity
- Familiar transaction semantics
- Blocks if the coordinator fails
- Locks held across network round trips
- Every participant must support XA-style prepare
- Availability is the product of all participants'
Pick it when: A few databases in one trusted environment, low volume.
Sagas plus outbox
- No cross-service locks
- Services stay independent
- Intermediate states are visible
- You write compensations
Pick it when: Most microservice workflows.
The bigger problem is coupling: a 2PC transaction is only as available and as fast as its slowest participant, and most third-party APIs (payment providers, email) can't take part at all. Consensus-backed systems like Spanner make distributed transactions practical inside one database, but across independent services the usual answer is sagas.
Crash the coordinator after every participant prepares, and watch the locks remain held.
Try it
Two-phase Commit Coordinator HLD
Build a coordinator and handle every crash point in 2PC.