CMD Guide
HomeSystem DesignMicroservices Patterns

The Saga Pattern A Solution

A saga keeps a multi-service business operation atomic without a distributed lock by breaking it into a sequence of local ACID transactions — each commits independently in its own service and database — and undoing any already-committed step with an explicit compensating transaction the moment a later step fails. There is no global rollback to fall back on, because each local commit is already durable and visible; the saga instead semantically reverses what was done. That single trade — swapping one distributed transaction for many local ones plus hand-written inverses — is the whole pattern, and every hard part below follows from it.

How the mechanism actually works

Each forward step Ti has a paired compensation Ci that semantically undoes it (refund, not "un-charge"; cancel order, not "delete row"). A saga log — held by the orchestrator, or reconstructed from the event stream in choreography — records which steps committed so recovery knows exactly how far to unwind.

Two recovery directions exist, and mixing them up is the classic design error. Backward recovery runs Ci … C1 in reverse order to abort. Forward recovery retries a failed step until it succeeds. You cannot always choose backward recovery, which forces the key classification of steps:

This ordering — all compensatable steps first, then the pivot, then only retriable steps — is what makes an eventually-consistent saga tractable. Put a non-compensatable side effect (an email) before the pivot and you can no longer honestly abort.

Order saga: stock reservation fails before the pivot; only the committed create-order step is compensated and the card is never charged
Order saga: stock reservation fails before the pivot; only the committed create-order step is compensated and the card is never charged

Traced example: an order that fails at inventory

Customer places order O-8842 for 2 units of SKU-19, total $250. The orchestrator drives the steps in the correct order — all compensatable steps first, then the pivot, then only retriable steps: T1 create order → T2 reserve stock → T3 charge $250 (the pivot) → T4 confirm/ship (retriable). Step 2 fails because only 1 unit is in stock — and because that failure lands before the pivot, the saga aborts backward and no money ever moves:

#StepService (local txn)ResultSaga log after
1T1 create order (compensatable)Order: insert O-8842, status PENDINGOK → emits OrderCreated[T1✔]
2T2 reserve stock (compensatable)Inventory: reserve 2×SKU-19FAIL — 1 available, business-rule violation[T1✔, T2✗]
3C1 compensate T1Order: set O-8842 status CANCELLEDOK (idempotent)[T1↩] → saga aborted

The pivot (T3 charge $250) and the retriable post-pivot step (T4 confirm/ship) never run — the saga aborted before reaching the point of no return. Two things stand out. First, because the pivot runs only after stock is reserved, a stock failure aborts before any money moved — you never refund a pivot. Contrast the anti-pattern: had we charged the card first and only then tried (and failed) to reserve stock, $250 would have really moved and we would have had to refund it — a genuine, externally-visible window of inconsistency. That is precisely why we reserve before we charge: the pivot belongs after every compensatable step it depends on. Second, T2 was not compensated: it failed, so it never committed, and only committed steps are compensated. And a step after the pivot — T4 confirm/ship — is likewise never compensated: once the pivot commits, a failing post-pivot step is retried forward until it succeeds, never rolled back. Concretely, if T4's "your order has shipped" email bounces, the saga retries the send forward — it does not abort a paid, shipped order to un-send a notification. This is exactly why non-compensatable side effects like email must sit after the pivot: they are retriable, not reversible.

The isolation problem — the caveat nobody mentions first

Local ACID transactions give you A, C, and D. Sagas throw away the I. Because each step commits immediately, its intermediate state is visible to other transactions before the saga finishes — the exact anomalies isolation was invented to prevent:

You manage this with saga-specific countermeasures (from Garcia-Molina's original work and Richardson's Microservices Patterns):

Choreography vs orchestration

These are the two ways to drive the sequence. In choreography there is no coordinator: each service subscribes to events and reacts (Order emits OrderCreated → Payment reacts and emits PaymentCaptured → Inventory reacts…). In orchestration a central saga orchestrator issues commands ("Payment: charge $250") and decides the next step from each reply.

The honest decision rule is not "simple vs complex" alone — it is about coupling, visibility, and cyclic dependencies:

Pitfalls a working engineer hits

When to use it — and when NOT to

Reach for a saga when a single business operation must update data owned by multiple services/databases, you cannot (or won't) run a distributed transaction across them, and the business can tolerate a brief window of inconsistency plus explicit compensation. Concrete signals: microservices with database-per-service, long-lived operations (checkout, booking, onboarding), or steps that span systems you don't control (payment gateways, shipping APIs).

Named alternative — 2PC / distributed ACID transaction (XA). 2PC gives you real isolation and an automatic atomic rollback: no compensations to write, no dirty reads. What it costs: a coordinator holds locks across all participants for the whole transaction, so throughput collapses under contention, tail latency spikes, and a coordinator crash after "prepare" leaves resources blocked (the blocking problem). Many cloud datastores and message brokers simply don't support XA. Sagas buy availability, low coupling, and long-lived operations at the price of lost isolation and hand-written, idempotent compensation logic.

Takeaways


Re-authored/Deepened for this guide. Sources: Hector Garcia-Molina & Kenneth Salem, "Sagas" (ACM SIGMOD, 1987) — the original long-lived-transaction paper and compensation model; Chris Richardson, Microservices Patterns (Manning, 2018) and microservices.io — saga orchestration/choreography, pivot & retriable classification, and countermeasures for lost isolation; Martin Kleppmann, Designing Data-Intensive Applications (O'Reilly, 2017) — 2PC, the blocking problem, and eventual consistency trade-offs.

🤖 Don't fully get this? Learn it with Claude

Stuck on The Saga Pattern A Solution? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **The Saga Pattern A Solution** (System Design) and want to truly understand it. Explain The Saga Pattern A Solution from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **The Saga Pattern A Solution** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **The Saga Pattern A Solution** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **The Saga Pattern A Solution** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes