~/notes/saga-pattern

Saga Pattern

A saga coordinates committed local transactions and compensating actions across a long-running workflow.

Jul 11, 2026

A saga represents a business workflow as a sequence of local Database Transactions. Each step commits independently. If a later step fails, the workflow runs compensating actions for earlier steps where compensation is possible.

A saga does not provide the isolation or instant rollback of one ACID transaction. Other processes can observe intermediate states, and compensation is a new business action rather than a database rollback.

Compensation

A useful compensation restores the business invariant, not necessarily the exact previous bytes.

Examples include releasing a reservation, issuing a refund, or adding a correcting ledger entry. Some actions are irreversible: an email cannot be unsent, a parcel may already be delivered, and an external price may have changed. The workflow must define escalation or forward recovery for those cases.

Compensations must themselves tolerate retries and failure.

Coordination

Orchestration uses a coordinator that records saga state and commands the next participant. It makes the workflow and recovery path visible in one place, but the coordinator must be durable and available.

Choreography has participants react to events without one workflow coordinator. It can reduce direct coupling, but long workflows become difficult to understand when sequencing and failure rules are distributed across consumers.

The choice affects ownership and observability, not the fundamental consistency model.

Reliability Requirements

A production saga needs:

  • a durable state for current step, attempts, and terminal outcome;
  • idempotency keys for commands and handlers;
  • transactional publication, usually through an outbox;
  • retry policies with bounded backoff;
  • timeouts and explicit handling of late responses;
  • compensation ordering and retry rules;
  • reconciliation for workflows that stop making progress;
  • audit history and operator controls.

Do not make remote HTTP or broker calls inside a local database transaction. Persist the state and outbound intent, commit, then perform the external interaction.

Further Reading