What is the Saga pattern?
A saga breaks a business operation into steps, each a local transaction in one service. When a step succeeds it triggers the next, either by publishing an event (choreography) or by being told what to do by a coordinator (orchestration). If a step fails, the saga runs compensating actions that undo the earlier steps, such as cancelling an order or refunding a payment.
What problem does the Saga pattern solve?
Two-phase commit across services is slow, holds locks, and is unsupported by most modern brokers and databases. Sagas give you a consistent business outcome without distributed locks, at the price of eventual consistency.
How do you implement the Saga pattern?
- List the steps and write a compensation for each one that can be undone.
- Choose choreography for short, simple flows and orchestration when there are many steps, branches or timeouts.
- Make every step and compensation idempotent, and persist the saga's state so it survives restarts.
- Order steps so the ones that cannot be undone (charging a card, sending an email) come last.
- Design the user experience for the in-between states, such as an order that is pending.
When should you use it?
- One business operation must update data in several services.
- You need an all-or-nothing business result but cannot use a distributed transaction.
When should you avoid it?
- The whole operation lives in one service. Use a normal local transaction.
- A step cannot be compensated and the business cannot tolerate partial results.
What do you gain?
- No distributed locks
- Services stay autonomous
- Failures have an explicit, testable recovery path
What does it cost?
- Eventual consistency, with visible intermediate states
- Compensation logic is real work
- Harder to debug without good tracing
What are common mistakes with the Saga pattern?
- Forgetting to compensate when a step times out and its outcome is unknown.
- Non-idempotent steps that run twice after a retry.
- Choreography across many services, which turns into a tangle nobody can draw.
Saga in practice
Ridgeway Rides
Booking a ride reserves a driver, places a hold on the rider's card and updates dispatch, each in a different service with its own database. A failure halfway left holds on cards with no ride attached.
Booking became an orchestrated saga with a compensation for each step. If no driver accepts in time, the orchestrator releases the card hold and cancels the dispatch entry, and every saga's state is visible in one place.
Example decision record
- Context
- Placing an order spans the order, payment and inventory services, each with its own database.
- Decision
- Implement order placement as an orchestrated saga with a compensating action for every step.
- Consequences
- The business transaction is eventually consistent without distributed locks.
- The orchestrator records each saga's progress, which gives an audit trail.