Sagas
A saga is a sequence of local transactions, one in each service, where each step commits in its own database and then triggers the next by publishing a message. When a step fails, the saga runs compensating actions for the steps that already succeeded. It is how a workflow that spans services gets something close to all-or-nothing without a shared transaction.
Why there is no rollback
Inside one database, a failed order is rolled back and nothing was ever written. Across services, each one has its own database and commits on its own. Payments has charged the card and committed. Nothing can reach into that database and take the commit back. Two-phase commit across services is generally not an option in a microservices setup, because each service owns its database and the broker is not part of the same transaction. The only way back is a new transaction that does the opposite.
The example
An order needs three steps. Inventory reserves the stock, Payments charges the card, Shipping books the delivery. If delivery cannot be booked, the saga refunds the payment and releases the stock.
| Step | Service | Action | Compensation |
|---|---|---|---|
| 1 | Inventory | ReserveStock | ReleaseStock |
| 2 | Payments | ChargePayment | RefundPayment |
| 3 | Shipping | BookDelivery | None, it is the last step. If it fails, steps 2 and 1 are compensated |
The saga can be run by choreography or orchestrationChoreography vs orchestrationServices reacting to each other's events, or one coordinator telling them what to do.Opens in a new tab. With orchestration, the orchestrator records each step and how to undo it, so it knows what to compensate.
What compensation is not
A compensation is not a perfect undo. The refund does not make the charge disappear: the customer may already have received a PaymentReceived email, and the refund is a second payment, not the first one removed. Microsoft’s guidance says a compensating transaction does not necessarily return the data to its state at the start, and it often needs business rules, for instance a refund that is smaller than the charge. Between the steps and the compensations, other requests can see the intermediate state, because sagas have no isolation.
Compensations must be safe to repeat
Compensations run after the original steps have committed, and they can fail like any other step. Messages are delivered at least once (see delivery guaranteesDelivery guaranteesAt-most-once, at-least-once and exactly-once: what a broker promises, and what it cannot.Opens in a new tab), so a compensation can also arrive twice. Make each one idempotent, so that a second RefundPayment for the same order does nothing (see idempotent consumersIdempotent consumersA consumer that gives the same result whether a message arrives once or five times.Opens in a new tab), and retry it with backoff until it succeeds (see retries and backoffRetries and backoffRun a failed message again after a growing, randomised delay, and stop after a limit.Opens in a new tab). The saga should record its progress so it can resume after a crash. If a compensation keeps failing, it ends up in a dead-letter queueDead-letter queuesWhere a message goes when it cannot be processed, so the rest of the traffic keeps moving.Opens in a new tab with an alert, because some failures need a person.
Ordering the steps
Some steps cannot be compensated, such as sending an email or handing a parcel to a courier. Put these after the steps that can fail, so that the saga reaches them only when the rest has already succeeded. Microsoft’s guidance calls this a point of no return and recommends placing irreversible steps after the critical checks.
Sources
- Pattern: Saga, microservices.io · accessed June 12, 2026
- Saga Design Pattern, Azure Architecture Center, Microsoft Learn · accessed June 12, 2026
- Compensating Transaction Pattern, Azure Architecture Center, Microsoft Learn · accessed June 12, 2026