OwlTheEngineer
System Design in 60 SecondsEpisode 44 · System design

Two-Phase Commit vs. Saga Pattern: distributed transactions in microservices

Why synchronous Two-Phase Commit (2PC) fails in cloud microservices, and how the asynchronous Saga pattern coordinates distributed transactions with compensating rollbacks.

Owl · 2 min read · 0 views
– comments
Ep 44 · System design
60s VISUAL BREAKDOWN
Episode 44
Watch the fast visual breakdown or discuss on social:

In monolithic architectures with a single relational database, maintaining data consistency is trivial. The application wraps multi-table operations inside a standard ACID transaction (BEGIN … COMMIT / ROLLBACK).

However, in a modern microservices architecture where each service owns its private database (e.g. Order Service, Payment Service, and Inventory Service), a single user transaction spans multiple independent databases.

How do you guarantee that an order isn’t charged if inventory reservation fails?

TWO-PHASE COMMIT (2PC - Blocking Locks):
Coordinator ──[1. PREPARE (Hold Locks)]──▶ Order DB, Payment DB, Inventory DB
Coordinator ──[2. GLOBAL COMMIT]─────────▶ Order DB, Payment DB, Inventory DB
Hazard: Single point of failure; all database locks freeze if coordinator dies.

SAGA PATTERN (Asynchronous Local Transactions + Compensations):
Step 1: Order DB commits OrderCreated ➔ Emits event
Step 2: Payment DB commits PaymentProcessed ➔ Emits event
Step 3: Inventory Out of Stock! ➔ Triggers Compensating Rollbacks:
        ➔ Refund Payment Service
        ➔ Cancel Order in Order Service

1. Why Two-Phase Commit (2PC) Breaks at Scale

Two-Phase Commit is a synchronous, blocking consensus protocol:

  1. Phase 1 (Prepare): The coordinator contacts all participants. Each service verifies constraints, reserves resources, and acquires pessimistic row locks.
  2. Phase 2 (Commit): If all nodes vote “YES”, the coordinator tells them to permanently commit.

The Critical Flaws of 2PC:

  • Lock Contention: Locked rows cannot be modified by any other request while waiting for Phase 2.
  • Coordinator Crash Vulnerability: If the transaction coordinator crashes between Phase 1 and Phase 2, participant databases are left in an indeterminate state with locked rows.
  • Latency Bottleneck: Transaction latency equals the slowest participating microservice + multiple network round trips.

2. The Saga Pattern Solution

The Saga Pattern structures a distributed business process as a sequence of independent local transactions:

  • Each microservice performs its local database operation, commits immediately, and emits an event or message to trigger the next step.
  • No global database locks are held.

Handling Failures with Compensating Transactions

Because local transactions commit immediately, a Saga cannot use a classic SQL ROLLBACK. Instead, if step $N$ fails, the Saga triggers Compensating Transactions—forward-recovery actions that semantically undo previous steps:

StepForward ActionCompensating Transaction (Undo)
1. Create OrderSet order status = PENDINGSet order status = CANCELLED
2. Charge PaymentCharge $50 to credit cardIssue $50 refund to credit card
3. Reserve InventoryDecrement item stock by 1Increment item stock by 1

3. Orchestration vs. Choreography Sagas

TypeArchitectureBest Use Case
ChoreographyServices listen to event brokers (Kafka / RabbitMQ) and trigger their step without a central controller.Simple 2–3 step workflows across loosely coupled services.
OrchestrationA dedicated state machine orchestrator (Temporal, AWS Step Functions) tells each service what to execute.Complex enterprise multi-step business workflows.

4. Production Architectural Guidance

  1. Make Compensating Transactions Idempotent: Due to network retries, a compensating transaction (like issuing a refund) may execute more than once. Always use idempotency keys.
  2. Design for Eventual Consistency: During a Saga execution, intermediate states are visible to other queries (e.g. an order in PENDING_PAYMENT state). Design frontend UI to handle asynchronous order status updates.
SYSTEM DESIGN CHECK

Test Your Understanding

Quick architectural scenario challenge based on this breakdown.

SCENARIO

A 3rd-party payment gateway starts timing out with 504 errors during peak traffic.

Q1.How should a downstream dependency failure be handled to protect upstream service availability?

Comments –