# Saga pattern

The saga pattern manages a business transaction across services as a sequence of local steps with compensating actions on failure. Learn choreography and orchestration.

## Overview

The saga pattern is a way to carry out one business transaction that spans several services or databases, without a single global transaction. The operation is split into a sequence of local steps. Each step commits in its own service. If a later step fails, the saga runs compensating actions that undo, in business terms, the steps that already succeeded. The system ends up either fully completed or consistently compensated, even though there was never one lock or commit across everything.

An everyday analogy is booking a holiday yourself. You book the flight, then the hotel, then the rental car, each with a different company. If the car company has nothing available, you do not get a magic "undo all" button. You cancel the hotel and cancel the flight, perhaps paying a fee. Each cancellation is a compensation. A saga is a planned version of that process, with each step and its cancellation defined in advance.

Sagas matter because [microservices](/tools/microservices) each own their data. An order that reserves stock, charges a card and schedules delivery touches three services and three databases. Classic distributed transactions using two-phase commit are often unavailable across services and brokers, and they reduce availability by holding locks across the network. Sagas trade immediate, all-or-nothing consistency for availability and loose coupling, with eventual consistency in between.

## What it is

A saga is defined by its steps, compensations and coordination style.

| Element | What it is | Example |
|---|---|---|
| Local transaction | A step that commits within one service | Reserve 2 units of stock |
| Compensating transaction | A step that semantically undoes an earlier one | Release the reserved stock |
| Pivot transaction | The point of no return; after it, the saga must complete | Capture the payment |
| Retriable transaction | A step after the pivot that must eventually succeed, retried until it does | Send confirmation email |
| Saga state | Record of which steps have completed | `PAYMENT_CHARGED` |
| Choreography | Services react to each other's events with no central controller | Payment listens for `StockReserved` |
| Orchestration | A coordinator tells each service what to do next | An order saga orchestrator calls each service |

Compensations are not database rollbacks. A refund is a new transaction that reverses the effect of a charge; the charge still happened and is visible in history.

## Where it came from

The term comes from a 1987 paper, "Sagas", by Hector Garcia-Molina and Kenneth Salem, presented at the ACM SIGMOD conference. They addressed long-lived transactions inside a database: transactions that hold locks for a long time and block others. Their proposal was to break such a transaction into a sequence of shorter transactions, each with a compensating transaction, so that the database could release locks between steps.

The idea was revived in the 2010s for distributed systems and microservices, where each service has its own database. Chris Richardson's writing on microservice patterns helped make "saga" the standard name for this approach, describing choreography and orchestration styles. Workflow engines such as [Temporal](/tools/temporal) and [Camunda](/tools/camunda) later offered built-in support for durable orchestration with compensation.

## How it works

### 1. Design the steps and compensations

List each step in order and define its compensation. Decide which step is the pivot. Steps before the pivot must be compensatable; steps after it must be retriable until success.

### 2. Choose coordination

**Choreography:** each service publishes events after its local transaction, and other services subscribe. The order service emits `OrderCreated`; inventory reserves stock and emits `StockReserved`; payment charges and emits `PaymentCharged`. There is no central controller. This suits short sagas with few participants.

**Orchestration:** a saga orchestrator holds the state and sends commands: "reserve stock", then "charge payment", then "schedule delivery". It reacts to replies and decides whether to continue or compensate. This suits longer or more complex sagas and makes the flow visible in one place.

### 3. Publish reliably

Each step must commit its local change and publish its event or reply together. The transactional outbox pattern writes the message to a local table in the same transaction, and a relay sends it to a broker such as [Apache Kafka](/tools/apache-kafka).

### 4. Handle failure

If a step fails for a business reason, such as a declined card, the saga runs compensations for completed steps in reverse order. If it fails for a technical reason, such as a timeout, it retries with backoff before deciding to compensate.

### 5. Make everything idempotent

Messages may be delivered more than once. Every step and compensation must give the same result if repeated, usually by tracking a saga ID and step ID.

### 6. Manage isolation

Because steps commit separately, other requests can see intermediate states. Countermeasures include semantic locks (marking an order `PENDING`), commutative updates and re-reading values before acting.

## Key concepts and terms

| Term | Meaning |
|---|---|
| Saga | A sequence of local transactions with compensations for one business operation. |
| Compensation | A business action that reverses an earlier step's effect. |
| Choreography | Decentralised coordination through events. |
| Orchestration | Central coordination by a saga orchestrator. |
| Pivot transaction | The step after which the saga will complete rather than compensate. |
| Transactional outbox | Writing outgoing messages in the same local transaction as data changes. |
| Idempotency | Repeating an operation has no extra effect. |
| Semantic lock | An application-level flag marking data as part of an in-progress saga. |
| Two-phase commit | A protocol for atomic commits across resources, which sagas avoid. |
| Eventual consistency | The system reaches a consistent state after the saga finishes. |
| Durable execution | Workflow engines that persist progress so long processes survive crashes. |

## A worked example

This scenario is illustrative. A food delivery platform handles an order through four services: Order, Kitchen, Payment and Courier. The team uses orchestration with a workflow engine.

The saga for order O-5521, total 34.50, runs as follows. Step 1, Order creates the order as `PENDING`. Step 2, Kitchen accepts it and reserves a preparation slot; compensation is cancelling the slot. Step 3, Payment authorises 34.50 on the customer's card; compensation is voiding the authorisation. Step 4, Courier assigns a rider within 10 minutes; compensation is releasing the rider. Step 5, the pivot, Payment captures the authorised amount. Step 6, Order marks the order `CONFIRMED` and sends a notification; this step is retried until it succeeds.

On a busy night no rider is available within 10 minutes. The Courier step returns `NoRiderAvailable`. The orchestrator runs compensations in reverse: void the card authorisation, cancel the kitchen slot, then mark the order `CANCELLED` and notify the customer. Total time from order to cancellation is 10 minutes and 4 seconds. The customer was never charged, because capture is after the pivot. During a broker outage, Payment receives the authorisation command twice; because it stores the saga ID, the second request returns the earlier result instead of authorising twice.

## Strengths and limitations

**Strengths:**

- Consistent business outcomes across services without distributed locks.
- Services stay loosely coupled and independently available.
- Compensation logic makes failure handling explicit and reviewable.
- Works with any database or message broker.
- Orchestration gives a clear, observable record of long-running processes.

**Limitations:**

- No isolation: intermediate states are visible to other operations.
- Compensations can be hard to design, and some actions, such as sending an email, cannot truly be undone.
- More code and testing for every failure path.
- Choreographed sagas become hard to follow as participants grow.
- Requires idempotency, reliable messaging and good monitoring.

## How it compares with alternatives

| Approach | How it works | When it fits better |
|---|---|---|
| Two-phase commit (XA) | Coordinator locks and commits all resources atomically | Few resources in one trusted environment that all support it |
| Single database transaction | Keep the data in one service and database | When the operation does not really need to span services |
| Outbox plus eventual updates | One service changes state and others follow from events | Simple propagation without business rollback |
| Workflow engines ([Temporal](/tools/temporal), [Camunda](/tools/camunda)) | Durable orchestration of steps with retries and compensation | Long-running or complex sagas; a way to implement orchestration |
| Manual reconciliation | Periodic jobs detect and fix inconsistencies | Low-volume processes where delay is acceptable; often a safety net |

## Practical guidance and best practices

1. First ask whether the boundary is right; if one operation always spans services, they may belong together.
2. Write down each step, its compensation, the pivot and the retriable steps before coding.
3. Put irreversible actions after the pivot, such as capturing payment or sending notifications.
4. Use the transactional outbox so state changes and messages cannot diverge.
5. Make every handler and compensation idempotent using saga and step identifiers.
6. Prefer orchestration once a saga has more than three or four participants.
7. Use semantic locks or pending states to prevent other requests acting on half-finished data.
8. Monitor stuck sagas and add alerts and a manual resolution path.
9. Test failure at every step, including failures during compensation.

## Common mistakes

- Assuming compensations always succeed and not handling their failure.
- Publishing events after commit without an outbox, losing messages on crashes.
- Placing irreversible actions early in the saga.
- Building long choreography chains that nobody can trace end to end.
- Ignoring duplicate deliveries, causing double charges or double reservations.
- Showing intermediate states to users as if they were final.

## Frequently asked questions

### Is a saga the same as a distributed transaction?

No. A distributed transaction provides atomic commit with isolation across resources. A saga gives eventual, business-level consistency through a series of local commits and compensations, without isolation.

### Choreography or orchestration?

Choreography works for short flows with few services and keeps services decoupled. Orchestration is easier to understand, test and monitor for longer flows, at the cost of a central coordinator.

### What if a compensation fails?

It must be retried until it succeeds, because leaving the saga half-compensated is inconsistent. If retries cannot succeed, the saga should be flagged for manual intervention.

### Can every action be compensated?

No. Some actions, like sending an email or shipping goods, cannot be undone. Place them after the pivot, or compensate with a follow-up action such as a correction message or a return process.

### Do I need a workflow engine?

Not always. Simple sagas can be built with messages and a state table. Workflow engines help when sagas are long, have timers, or need durable state and visibility.

### Where did the name come from?

From the 1987 paper "Sagas" by Hector Garcia-Molina and Kenneth Salem, which proposed splitting long-lived database transactions into smaller steps with compensations.

## Glossary

- Saga: a multi-step business transaction with compensations.
- Local transaction: a commit within one service.
- Compensating transaction: an action that reverses an earlier step's effect.
- Pivot: the point after which the saga completes.
- Orchestrator: the coordinator of an orchestrated saga.
- Choreography: coordination by events without a coordinator.
- Outbox: a local table for messages written in the same transaction.
- Idempotency key: an identifier used to detect repeated requests.
- Semantic lock: an application flag marking in-progress data.

## Summary

The saga pattern coordinates a business transaction across services as a series of local transactions, each paired with a compensation that reverses its effect if a later step fails. It dates from Garcia-Molina and Salem's 1987 paper and became the standard approach to consistency in microservices. Sagas can be choreographed through events or orchestrated by a coordinator or workflow engine. They require careful ordering around a pivot, reliable messaging with an outbox, idempotent steps, handling of visible intermediate states and thorough testing of every failure path.
