Stackbook Logo
data-consistency

Saga Pattern Implementation

Intent

Coordinate multi-service business transactions through a sequence of local transactions and compensating actions.

Problem

Distributed transactions with two-phase commit are impractical across independent services and databases. Without them, a failure partway through a business process leaves data inconsistent across services.

Forces

    Solution

    Saga Pattern Implementation

    A saga replaces one large atomic transaction with a chain of smaller ones, accepting temporary inconsistency in exchange for autonomy and availability. Correctness comes from compensations and careful state tracking.

    How it works

    In orchestration, a coordinator sends a command to the first service, waits for its outcome, and then commands the next. Each service commits its local transaction and replies. If a step fails, the orchestrator issues compensating commands for completed steps in reverse order, such as refunding a payment or releasing reserved stock. In choreography, services publish events and others subscribe, with failure events triggering compensations. Saga state is persisted so processing can resume after crashes, and steps use idempotency keys to tolerate redelivery.

    Implementation steps

    1. Model the process as ordered local transactions
    2. Define a compensating action for every reversible step
    3. Choose orchestration for complex flows or choreography for simple ones
    4. Persist saga state and use an outbox for reliable messaging
    5. Make steps and compensations idempotent and retryable
    6. Add timeouts, monitoring, and a manual intervention path for stuck sagas

    Common pitfalls

    • Compensations that assume the original step fully succeeded
    • Missing semantic locks, allowing other transactions to see or change pending data
    • Lost messages when publishing events outside the local transaction
    • No handling for compensation failures

    Metrics to watch

    • Saga completion and compensation rates
    • Duration of sagas by step
    • Number of stuck or timed-out sagas
    • Compensation failure count
    • Retries per step

    Example configuration

    # Orchestrated order saga
    saga: place-order
    steps:
      - name: reserve-stock
        action: inventory.reserve
        compensation: inventory.release
      - name: charge-payment
        action: payments.charge
        compensation: payments.refund
      - name: create-shipment
        action: shipping.create
        compensation: shipping.cancel
    onFailure: compensate-reverse
    timeout: 5m
    

    Trade-offs and adoption

    Teams adopt this approach when a business process spans multiple services with separate data stores; two-phase commit is unavailable or too costly. It is a poor fit when a single database transaction can cover the whole operation, or when steps cannot be compensated and intermediate states are unacceptable. The central tensions are choreography flexibility vs orchestration clarity; isolation vs availability; compensation completeness vs implementation effort. The main benefits are that it delivers: avoids distributed locks and two-phase commit; services remain autonomous and loosely coupled; explicit handling of failure paths; supports long-running workflows. The main costs to budget for are: intermediate states are visible to other users; compensations are hard to design correctly; complex debugging across services; requires idempotent steps and reliable messaging. Governance typically looks like this: each saga has a named owner and documented compensation semantics. Expect adoption cost to be high: workflow state, messaging, and compensations, and a best fit for medium to large teams with service-per-database architectures. Critics point out that lack of isolation permits anomalies that are hard to reason about, and that choreographed sagas become tangled and difficult to understand as steps grow. Treat these concerns as design inputs, and revisit the decision as traffic, team size, and failure history change.

    Key takeaways

    • Design compensations as carefully as forward steps
    • Persist saga state and make steps idempotent
    • Use orchestration when flows grow complex
    • Plan for visible intermediate states and stuck sagas

    ✓ When to Use

    • •A business process spans multiple services with separate data stores
    • •Two-phase commit is unavailable or too costly
    • •Steps can be meaningfully compensated
    • •Long-running processes need visible progress and recovery

    ✗ When Not to Use

    • •A single database transaction can cover the whole operation
    • •Steps cannot be compensated and intermediate states are unacceptable
    • •The process is simple enough that a synchronous call with retry suffices

    Pros

    • +Avoids distributed locks and two-phase commit
    • +Services remain autonomous and loosely coupled
    • +Explicit handling of failure paths
    • +Supports long-running workflows

    Cons

    • −Intermediate states are visible to other users
    • −Compensations are hard to design correctly
    • −Complex debugging across services
    • −Requires idempotent steps and reliable messaging

    Cost Profile

    Infrastructure

    Operational

    Cognitive

    Failure Modes

      Alternatives

        Related Patterns

          Competency Domains

          data statedistribution communicationreliability ops