advanced 2 min answer

A shipping aggregator books a shipment across carrier, warehouse, payment and notification systems, with no shared transaction available. Which coordination pattern fits, and what are the compensations that cannot exist?

shiprocketsagacompensationlogisticsorchestration
Show the full answer Hide the answer

Why a saga, and orchestrated rather than choreographed

There is no distributed transaction across an external carrier's API, your warehouse system and a payment provider. The available pattern is a saga: a sequence of local transactions, each with a compensating action, coordinated so that a failure at step four undoes steps one to three.

Orchestration is the right variant here because the sequence is business-visible, involves external parties, and someone will be asked "where is this shipment?" A central orchestrator holds the state and can answer. Choreography — each service reacting to events — spreads the sequence across services with no single place that knows the current state, which is workable for simple flows and miserable for a flow with external dependencies and a support team.

The ordering rule

Do the reversible things first and the irreversible things last. Reserve inventory (reversible), authorise payment (reversible), book the carrier (semi-reversible — cancellation windows and fees), capture payment (reversible via refund), dispatch (irreversible), notify (irreversible).

Every step you move later is a compensation you might never need to run.

The compensations that cannot exist

  • A notification cannot be unsent. The compensation is a second notification, which is a different thing and visible to the customer. This is why notification goes last and why it should never be inside the critical sequence.
  • A physical pickup cannot be undone once the courier has collected. The compensation is a return journey, with real cost.
  • A carrier booking past its cancellation window incurs a fee. The compensation exists but it is not free, which means the saga's failure path has a cost the business must accept explicitly.

When a compensation is expensive or impossible, the correct response is to move that step later or to add a confirmation gate before it — not to write a compensating action that lies about being able to undo.

What the saga must have to be operable

  • Idempotent steps and idempotent compensations. Both will be retried.
  • A durable state machine, so a crashed orchestrator resumes rather than restarts.
  • A terminal state for every path, including "compensation failed" — which must page a human rather than retry forever, because a stuck compensation is money or goods in an unknown state.
  • A reconciliation against the carrier's own record, because the carrier is the authority on what was actually booked and your view of it is a cache.

The honest trade

Sagas trade atomicity for availability, and what you get in exchange for that is intermediate states that are visible to users. A customer can see "payment taken, shipment not booked" for thirty seconds. That has to be designed into the product — a status the interface can express — rather than treated as an anomaly.