System Design Space
Knowledge graphSettings

Updated: June 24, 2026 at 1:28 PM

Distributed Transactions: 2PC and 3PC

hard

A practical look at distributed transactions: coordinator and participants, two-phase and three-phase commit, blocking, partial failures, and alternatives via Saga and transactional outbox.

Distributed transactions become painful exactly where the business wants atomicity but the architecture has already split across multiple services and stores.

In real engineering work, this chapter helps choose between 2PC, 3PC, Saga, and transactional outbox by domain boundaries, acceptable failure behavior, blocking risk, and coordination cost.

In interviews and design conversations, it is especially useful when you need to speak plainly about timeout semantics, partial commit, compensations, and idempotency requirements.

Practical value of this chapter

Design in practice

Helps choose transaction patterns by domain boundaries and acceptable failure behavior.

Decision quality

Compares 2PC, 3PC, and Saga by latency, locking impact, and operational complexity.

Interview articulation

Provides a clear narrative for coordinator, participants, commit point, and recovery.

Risk and trade-offs

Makes blocking, partial-commit, timeout, and idempotency trade-offs explicit.

Context

Consistency and idempotency

Distributed transactions are one way to ensure consistency, but not the only one.

Open chapter

Distributed transactions: two-phase commit (2PC) and three-phase commit (3PC) are needed where a business invariant requires changing several independent resources as one unit and an intermediate state is unacceptable. The price of that atomicity is extra latency, blocking, and the very recovery-after-partial-failure that the protocols exist to handle.

When is a distributed transaction needed?

  • One business operation must atomically change several independent resources or services, and splitting it into separate steps is not an option.
  • Even temporary divergence does not survive here — an intermediate result already counts as an error.
  • When a commit lands only partially, the cost moves straight into finance, regulation, or what the user sees.

How two-phase commit (2PC) works

2PC: two-phase commit

Prepare -> votes -> global decision (commit/abort)

The coordinator collects participant votes and makes one global commit/abort decision for the whole transaction.

Strengths

  • Simple coordination model that is easy to reason about.
  • Clearly separates preparation from the final decision.

Risks

  • Blocking is possible if the coordinator fails at the wrong time.
  • Highly sensitive to timeout/retry tuning.

Protocol Steps

Current Command

Click Start to play the protocol step-by-step.

Coordinator

Waiting to start

Coordinator commands: 0

Participants

3 participants

Active step: 0 / 8

Order

participant A

Waiting for commands

Involved in steps: 0

Payment

participant B

Waiting for commands

Involved in steps: 0

Inventory

participant C

Waiting for commands

Involved in steps: 0

How three-phase commit (3PC) works

3PC: three-phase commit

CanCommit -> PreCommit -> DoCommit

Adds an intermediate PreCommit phase to reduce blocking risk when the coordinator has issues.

Strengths

  • Reduces the chance of getting stuck in an uncertain state.
  • Explicitly separates intent from final commit.

Risks

  • More network rounds and a more complex state machine.
  • Requires very careful timeout and recovery tuning.

Protocol Steps

Current Command

Click Start to play the protocol step-by-step.

Coordinator

Waiting to start

Coordinator commands: 0

Participants

3 participants

Active step: 0 / 12

Order

participant A

Waiting for commands

Involved in steps: 0

Payment

participant B

Waiting for commands

Involved in steps: 0

Inventory

participant C

Waiting for commands

Involved in steps: 0

Alternative

Event-Driven Architecture

More often than it looks, Saga plus transactional outbox is a better fit than global 2PC/3PC: no blocking, and consistency reached step by step.

Open chapter

Trade-offs and alternatives

2PC is easy to explain and adopt. The bill arrives when the coordinator fails after the prepare phase: participants stay blocked and hold their resources until it comes back.

3PC removes that hang at the cost of one more network round — and the protocol state machine grows with it, which someone now has to maintain correctly.

Network partitions, timeouts, and recovery after partial failures hit both protocols the same way: the error does not fail loudly, it leaves the transaction in an in-doubt state.

In a microservice architecture, a shared atomic transaction across services is almost always more expensive and more fragile than the diagram suggests — coupling grows, and one stuck participant slows the rest.

Saga (orchestration/choreography)

The operation splits into local steps, each with its own compensating action. There is no atomicity — in return, the global lock and the coordinator as a single point of failure both disappear.

Transactional outbox

The event is written in one local transaction together with the business change, and a separate worker publishes it later. That removes the risk of the database write and the message drifting apart.

Idempotent commands + reconciliation

When a retried command is safe, a partial failure stops being a catastrophe: background reconciliation drives the system back to a consistent state instead of a manual cleanup.

Domain redesign

The cheapest way to handle a distributed transaction is to not have one. Move aggregate boundaries so the invariant lives inside a single service.

Practical checklist

  • The boundary is drawn explicitly: where strict atomicity is truly needed, and where eventual consistency is enough.
  • The coordinator has a recovery strategy and a durable log — after a restart it knows which transactions are left in-doubt.
  • Timeout policies are tested not on the happy path but under network partitions and delays.
  • A repeated COMMIT or ABORT does not break a participant — the handling is idempotent.
  • For disputed cases there is a business mechanism for compensation and manual resolution, not just hope that the automation gets it right.

Frequent anti-pattern: introducing 2PC between services as “just a transaction,” without first costing the blocking, the retry model, and the recovery — and then learning about them in production.

References

Related chapters

Enable tracking in Settings