---
title: "Run a change across services as a saga · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/system-architecture/sagas
id: ARC-91
level: Recommended
updated: 2026-10-27
build: a2a6bdfed830
tokens: 995
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Run a change across services as a saga with undo steps

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [System architecture](https://agentwranglers.se/playbook/architecture/system-architecture.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: ARC-91
- Level: Recommended
- Chapter: [System architecture](https://agentwranglers.se/playbook/architecture/system-architecture.md)
- Rule: When one business action changes data owned by two or more services, run it as a saga. Each step commits locally, and each step that can fail later has an undo step that runs on failure.
- Check: A test fails each step in turn and finds every earlier step undone, such as the stock released and the card refunded. A second test restarts the coordinator mid-saga and finds the saga finished.
- How: One database transaction cannot span services that own their own data. Split the action into local steps, such as reserving stock, charging the card and booking shipping. Give every step before the point of no return a compensating step, such as releasing the stock or refunding the card. Steps after that point must be safe to retry until they succeed. Either one coordinator runs the steps, or each service reacts to the event before it. Make every step and undo step idempotent, as [Make receivers idempotent](https://agentwranglers.se/playbook/events/consuming-events/idempotent-consumers.md) says. Keep the saga's state in storage so a restart picks it up. Inside one service, a local transaction and the [outbox](https://agentwranglers.se/playbook/events/publishing-events/outbox.md) are simpler.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### TypeScript example

```ts
// Orchestrated saga: undo the finished steps in reverse order on failure
const steps = [
  { run: reserveStock, undo: releaseStock },
  { run: chargeCard, undo: refundCard },
  { run: bookShipping, undo: cancelShipping },
];

async function placeOrder(order: Order) {
  const done: typeof steps = [];
  try {
    for (const step of steps) { await step.run(order); done.push(step); }
  } catch (error) {
    for (const step of done.reverse()) await step.undo(order);
    throw error;
  }
}
```

### Python example

```python
# Orchestrated saga: undo the finished steps in reverse order on failure
STEPS = [(reserve_stock, release_stock), (charge_card, refund_card), (book_shipping, cancel_shipping)]

async def place_order(order: Order) -> None:
    done = []
    try:
        for run, undo in STEPS:
            await run(order)
            done.append(undo)
    except Exception:
        for undo in reversed(done):
            await undo(order)
        raise
```

## Sources

- [Microsoft: Saga design pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/saga)

## Related rules

- EVT-11 [Process each message once](https://agentwranglers.se/playbook/events/consuming-events/idempotent-consumers.md) in Integration and events
- EVT-6 [Send side effects through an outbox](https://agentwranglers.se/playbook/events/publishing-events/outbox.md) in Integration and events

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/architecture/system-architecture/sagas">Agent Wranglers clean code and architecture playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Give each outside dependency its own pool](https://agentwranglers.se/playbook/architecture/system-architecture/bulkheads.md)
- [System architecture](https://agentwranglers.se/playbook/architecture/system-architecture.md)
