Distributed Transactions (2PC/Saga)
Overview
A distributed transaction coordinates a single logical change across multiple services or databases so the work either fully completes or fully unwinds. Two-phase commit enforces this with a coordinator that locks participants until all agree, while the Saga pattern breaks the work into local steps with compensating actions that undo prior steps on failure.
Key Concepts
Two-phase commit (2PC)
Uses a coordinator and a set of participants:
- Prepare phase: the coordinator asks every participant to prepare and to promise it can commit; each votes yes or no and holds locks.
- Commit phase: if all voted yes, the coordinator tells everyone to commit; otherwise it tells everyone to abort.
Saga
Avoids global locks by running a chain of local transactions, each publishing an event that triggers the next. If a step fails, the Saga runs compensating transactions to reverse the completed steps (for example, refund a payment after a failed shipment).
Sagas come in two flavors: choreography, where services react to each other's events, and orchestration, where a central coordinator drives the sequence. Because steps and compensations may be retried, each must be idempotent. Sagas trade the strict atomicity of ACID and BASE for availability and eventual consistency.
| Aspect | Two-phase commit | Saga |
|---|---|---|
| Consistency | Strong, atomic | Eventual |
| Locks | Holds locks across services | No cross-service locks |
| Failure handling | Coordinator aborts all | Compensating transactions |
| Weakness | Coordinator is a blocking single point | Compensation logic is complex |
Trade-offs
2PC gives clean atomicity but is a blocking protocol: participants hold locks while waiting, and if the coordinator crashes mid-commit, participants can be stuck in doubt, which hurts availability and throughput. Sagas stay available and lock-free but expose intermediate states and force you to design a correct compensating action for every step, which is often the hardest part. Many systems avoid both by redrawing service boundaries so a transaction stays within one service.
Interview Tips
- Lead with the problem: no single database spans the services, so you need a coordination protocol.
- Prefer Sagas for high-throughput microservices and reserve 2PC for tightly coupled, low-volume cases.
- Always mention compensating transactions and that Saga steps must be idempotent to survive retries.
- Call out 2PC's blocking coordinator as its defining weakness.
Summary
- A distributed transaction makes a change across multiple services succeed or fail as a unit.
- Two-phase commit uses a coordinator and prepare/commit phases to enforce atomicity with locks.
- The Saga pattern chains local transactions and undoes them with compensating transactions on failure.
- Sagas can be choreographed via events or orchestrated by a central controller.
- 2PC offers strong consistency but blocks; Sagas stay available but require idempotent, compensable steps.