DEV Community

Cover image for Saga Pattern
kevinrawal
kevinrawal

Posted on Originally published at papers-by-kevin.vercel.app AI-assisted

Saga Pattern

The Problem

In a microservices app, one user action often touches several services.
Take an e-commerce order:

Order Service → Payment Service → Inventory Service
Enter fullscreen mode Exit fullscreen mode

Each service has its own database. Now what if the payment succeeds but the item is out of stock? We can't just call ROLLBACK, because no single transaction spans three databases.

How do we undo things properly when one step fails?

Option A: One Big ACID Transaction

A relational database gives us ACID guarantees, and a single transaction can roll everything back. But this only works inside one database.

  • Microservices own separate databases, so one transaction can't cover them all.
  • Sharing one database between services couples them tightly.
  • Rows stay locked for the whole flow, which hurts speed and scalability.

Option B: Two-Phase Commit (2PC)

A coordinator asks every service "can you commit?" (prepare phase), and only if all say yes does it say "commit" (commit phase).

  • Resources stay locked while everyone waits, so it is slow.
  • If the coordinator crashes mid-way, services are stuck.
  • Many modern databases and message brokers don't support it.

It works, but it doesn't scale well for microservices.

Option C: Saga Pattern ✅

A saga splits the big transaction into a sequence of small local transactions, one per service. Each step has a matching compensating transaction that undoes it.

Happy path

Create Order → Deduct Payment → Reserve Stock → ✅ Done
Enter fullscreen mode Exit fullscreen mode

Failure path (out of stock)

Create Order → Deduct Payment → Reserve Stock ❌
                                      │
         Cancel Order ← Refund Payment ◄┘
Enter fullscreen mode Exit fullscreen mode

Payment was deducted but the item is out of stock? The saga triggers a refund and the order is cancelled. The customer gets the money back.

Two Ways to Run a Saga

Style How it works Good for
Choreography Services publish events and react to each other's events. No central boss. Simple flows with few services
Orchestration A central orchestrator tells each service what to do next, and what to undo on failure. Complex flows, easier to track

Trade-offs

  • The system is eventually consistent, so for a moment the money may be deducted before the refund lands.
  • Compensating actions must be idempotent, meaning safe to run more than once.
  • More code, because you write a "undo" for every step.

TL;DR

Can't roll back across services? Do each step locally, and if something fails, run the undo steps for the ones already done.

Top comments (0)