Saga Pattern
A way to manage distributed transactions across microservices using a sequence of local transactions with compensating actions for rollback.
What is Saga Pattern?
In short
The Saga pattern manages a business transaction that spans multiple microservices by splitting it into a sequence of local transactions, where each service commits its own work and publishes an event or message that triggers the next step. If any step fails, the saga runs compensating transactions that undo the earlier committed steps, giving you eventual consistency without a distributed lock or two-phase commit.
What the Saga pattern is
In a single database you can wrap several writes in one ACID transaction and roll the whole thing back if anything fails. Once your data is spread across separate services, each with its own database, that trick stops working. There is no shared transaction that can lock rows in the order service, the payment service, and the inventory service all at once.
A saga solves this by turning one big transaction into a chain of small local transactions. Each service does its own piece, commits it immediately, and then hands off to the next service. A travel booking saga might be: reserve flight, then charge card, then reserve hotel. Each step is fully committed in its own service before the next one starts.
Because there is no global rollback, every step that can change data must also define a compensating transaction that semantically undoes it. Cancel the flight reservation, refund the card, release the hotel room. If step 3 fails, the saga walks backward and runs the compensations for steps 2 and 1. The system ends up consistent again, just not instantly.
How it works under the hood
There are two common ways to coordinate the steps. Choreography is event-driven and has no central brain: each service listens for events on a message broker like Kafka or RabbitMQ, does its work, and emits a new event that the next service reacts to. It is loosely coupled and easy to start with, but the overall flow is implicit and hard to trace once you have more than three or four steps.
Orchestration uses a central coordinator, often called a saga orchestrator, that tells each service what to do and waits for the reply. The orchestrator holds the saga state machine: which step we are on, what to call next on success, and what compensation to call on failure. Frameworks like Temporal, AWS Step Functions, Camunda, and Axon implement this. The flow is explicit and observable, at the cost of one more moving part.
Either way, two properties are non-negotiable. Steps and their compensations must be idempotent, because the broker will redeliver messages and the orchestrator will retry after crashes, so running the same step twice must not double-charge a card. The saga state must also be persisted durably after each step, so a crash mid-saga can be recovered and resumed rather than left half-finished.
When to use it and the trade-offs
Reach for a saga when one user action must update several services and you cannot or do not want a distributed two-phase commit, which holds locks across services and kills availability. Order checkout, money transfers between accounts, and multi-step provisioning are the classic cases.
The big trade-off is that you give up isolation. A saga is not atomic from an outside observer's point of view. Halfway through, other reads can see the flight booked but the card not yet charged. You have to design for these intermediate states, often with a pending or reserved status, and accept dirty reads or use semantic locks to guard against them.
Compensations are also harder than they look. Some actions cannot be cleanly undone. You cannot un-send an email or un-ship a package, so the compensation becomes a counter-action like sending an apology or issuing a return label. If a compensation itself fails, you usually retry it forever and alert a human, because a saga must eventually reach either fully committed or fully compensated. There is no in-between resting state.
A concrete example
Picture an e-commerce checkout built as four services. The Order service creates an order in PENDING state. The Payment service charges the customer. The Inventory service decrements stock. The Shipping service schedules a delivery. Each writes to its own database and emits an event.
Now suppose payment succeeds and stock is decremented, but the Shipping service reports the address is undeliverable. The saga triggers compensations in reverse: Inventory adds the stock back, Payment issues a refund, and Order moves to CANCELLED. The customer sees a clean cancellation and a refund, even though three different databases were touched along the way.
Compare that to the failure mode without compensations: money taken, stock removed, no shipment, and an angry customer. The saga's job is to guarantee that the business outcome is all-or-nothing even though the data writes were not. That guarantee is eventual, measured in seconds to minutes, not the millisecond atomicity of a single-database transaction.
Where it is used in production
Uber (Cadence / Temporal)
Uber built Cadence, now open-sourced and continued as Temporal, to run long-lived sagas for trips and payments as durable workflows with automatic retries and compensations.
AWS Step Functions
Provides a managed orchestrator where each saga step is a Lambda or service call and the state machine encodes success paths plus catch-and-compensate branches.
Netflix Conductor
An open-source workflow orchestration engine Netflix used to coordinate microservice business flows, including saga-style compensation on failure across content and billing pipelines.
Apache Kafka
The common backbone for choreography-based sagas, where each service consumes domain events and publishes the next event to drive the transaction forward.
Frequently asked questions
- What is the difference between a saga and a two-phase commit?
- Two-phase commit (2PC) is atomic and isolated: a coordinator locks all participants, then commits or aborts everyone together, so nobody ever sees a half-done state. But it holds locks across services and blocks if the coordinator dies. A saga avoids distributed locks by committing each step locally and undoing failed work with compensations, trading isolation and instant atomicity for availability and eventual consistency.
- Choreography or orchestration, which should I use?
- Start with choreography for simple sagas of two or three steps where loose coupling matters and the flow is obvious. Switch to orchestration once you have many steps, complex branching, or a need to see and debug the whole transaction in one place, since a central orchestrator makes the state machine explicit and observable.
- What is a compensating transaction?
- It is the action that semantically undoes a previously committed step. If a step charged a card, its compensation issues a refund; if a step reserved inventory, its compensation releases it. Compensations rarely restore the exact prior state, they produce a new state that is business-equivalent to the step never having happened.
- Why do saga steps have to be idempotent?
- Message brokers redeliver messages and orchestrators retry after crashes, so the same step or compensation can be invoked more than once. Idempotency, usually enforced with a unique request or transaction ID, ensures that processing a duplicate has no extra effect, so a retried payment step does not charge the customer twice.
- Does a saga guarantee consistency?
- It guarantees eventual consistency, not the immediate consistency of a single ACID transaction. During the saga other parts of the system can observe intermediate states, and the data only converges to a fully committed or fully compensated outcome once all steps finish. You design around the in-flight states rather than pretending they do not exist.
Learn Saga Pattern hands-on
This page explains the idea. The full lesson lets you step through the ring as servers join and leave, read the implementation, and check yourself with a quiz. It is one of 760+ lessons in the System Design Masterclass, from your first API call to distributed consensus. Eleven Foundation lessons are free, no signup. Lifetime access is ₹499 in India or $7.99 worldwide, one payment, no subscription.
Related lessons
Lessons that touch on Saga Pattern as part of a larger topic.
See also
Related glossary terms you might want to look up next.
CQRS
Command Query Responsibility Segregation: using different models for reading and writing data. Reads and writes have different performance needs, so separate them.
Event Sourcing
Storing every state change as an immutable event instead of just the current state. You can rebuild any past state by replaying events.
Two-Phase Commit
A protocol ensuring all nodes in a distributed transaction either commit or abort together. Phase 1: prepare (vote). Phase 2: commit or rollback.
CAP Theorem
In a distributed system, you can only guarantee two of three: Consistency, Availability, and Partition tolerance. You must choose your trade-off.
Consensus
The process of getting multiple nodes in a distributed system to agree on a single value. The foundation of distributed databases and coordination services.
Paxos
A family of protocols for solving consensus in unreliable networks. Famously difficult to understand but mathematically proven correct.