SweatyImposterDistributed Transactions: 2PC vs Saga

Distributed Transactions: 2PC vs Saga

2PC offers strong consistency across services at a heavy cost; Saga gives you eventual consistency via compensating transactions.

What it is

Two-Phase Commit (2PC) coordinates a transaction across multiple databases or services in two phases: prepare (everyone votes yes/no) and commit (coordinator tells everyone to commit or abort). It provides ACID (Atomicity, Consistency, Isolation, Durability) across the participants but blocks if the coordinator fails between phases. The Saga pattern instead breaks the transaction into a sequence of local transactions, each with a compensating action; if step 3 fails, you run compensations for steps 1 and 2. Sagas trade atomicity for availability and partition tolerance.

Why senior interviewers ask

Microservices interview questions almost always include 'how do you keep data consistent across services?' Knowing 2PC vs Saga and the failure modes of each is a senior signal.

Key points

  • 2PC: synchronous, blocking, ACID across participants — but coordinator failure = stuck in-doubt state.
  • 2PC participants hold locks during the prepare phase; latency = slowest participant.
  • Saga: asynchronous, eventually consistent — each step is a local transaction with a compensating action.
  • Orchestrated saga: central coordinator drives the steps (easier to reason about).
  • Choreographed saga: each service emits events that trigger the next step (looser coupling, harder to debug).
  • Compensations are NOT rollbacks — they're forward-running transactions (refund payment, not 'undelete charge').
  • Sagas require idempotent steps and compensations because retries are inevitable.

Pros

  • 2PC: true atomicity across systems; familiar transactional model.
  • Saga: scales horizontally; works across services with separate databases.
  • Saga: tolerates partitions and slow participants gracefully.

Cons

  • 2PC: blocking protocol; coordinator failure leaves participants stuck holding locks.
  • 2PC: latency = sum of all participant latencies; doesn't fit microservices.
  • Saga: no isolation — intermediate states are visible to other transactions.
  • Saga: compensations are hard to design correctly (what does 'undo email sent' look like?).

When to choose

  • 2PC: small number of participants, low latency between them, strong consistency required (rare — usually within one DB cluster).
  • Saga: microservices with separate databases and unavoidable distributed workflows.
  • Saga: long-running business processes (order fulfillment, travel booking).

When to avoid

  • 2PC: across services owned by different teams or in different regions — failure modes are nasty.
  • Saga: when compensations are not physically possible (you can't un-send a tweet).

Real systems

XA TransactionsJava/JTA standard for 2PC across multiple resource managers; widely deprecated in new systems.
AWS Step FunctionsOrchestration platform commonly used to implement sagas with built-in retries and compensation.
Temporal / CadenceDurable workflow engines designed for long-running sagas with automatic retries.
Spanner / CockroachDBDistributed SQL hides 2PC inside the database — applications get ACID for free at the latency cost.

Interview probe

'Order service charges card, inventory service reserves stock, fulfillment service ships. What if shipping fails?' Answer: saga with compensations — refund the charge, release the stock. Don't say 2PC across three services.

All database concepts