Order Orchestration and Saga Patterns

Order-to-cash is a multi-system transaction without a transaction coordinator: payment, allocation, picking, shipping, and invoicing each commit locally, and any step can fail after earlier steps committed. The saga pattern — a sequence of local transactions, each paired with a compensating action that semantically undoes it — is the standard answer, covered generically in MicroservicesArchitecture and SoftwareArchitecture. This page is the commerce-specific application: what the order saga actually looks like, choreography vs orchestration at each scale tier, and the open-source engines that run it.

The Order Saga, Concretely

step                          compensation
───────────────────────── ─────────────────────────
authorize payment             void authorization
allocate inventory            release allocation
release to WMS                cancel pick task (if not picked)
pick + pack                   restock items
ship (label, manifest)        — point of no return —
capture payment               refund
invoice to ERP                credit note

Three design facts fall out of writing the table. First, compensations are business decisions, not technical inverses — "cancel after pick" means restocking labor, and "cancel after ship" means a returns flow, so where you allow cancellation is a policy the state machine must encode. Second, there is a point of no return (carrier handoff): after it, failure handling switches from compensation to the returns process. Third, every step must be idempotent and every compensation must tolerate the step having half-happened (DataConsistencyAndSyncPatterns) — sagas run on at-least-once rails.

Choreography vs Orchestration

Choreography — no coordinator; each service reacts to events (payment hears OrderPlaced, inventory hears PaymentAuthorized…). Fewest moving parts, natural at garage/growth tier where three services chain linearly. Its failure mode is invisibility at scale: nobody owns the whole flow, so "where is order 4711 stuck, and why?" becomes archaeology across four services' logs, and adding a step means touching every neighbor.

Orchestration — an explicit coordinator owns the order state machine, commands each step, and handles failures per its policy. One place to read the flow, one place to see every stuck order, one place to change the process. Its cost: the orchestrator is real infrastructure with state that must survive crashes.

The honest tier mapping: garage — the monolith is the orchestrator (a status column plus careful code; enjoy it). Growth — choreography over the broker for the happy path, plus the reconciliation net for escapes; or an early lightweight orchestrator. Enterprise — explicit orchestration, because operability ("show me all orders stuck in allocation > 30min, by cause") stops being optional.

Open-Source Engines (and the Licensing Trap)

Exceptions Are the Actual Product

Happy-path orchestration is a week of work; the value is in the exception catalog, and pick/pack operations generate them daily: partial pick (3 of 4 items on the shelf — split-ship or hold-and-wait is a policy, encode it), payment capture fails after ship (dunning path, not a crash), customer cancels mid-flow (race against the point of no return — the state machine answers atomically), carrier rejects the manifest (re-rate and relabel, don't strand the box), backorder (the allocation step gains a waiting state with customer messaging). A useful heuristic for engine choice: if your exception catalog fits in the monolith's code legibly, you don't need an engine yet; when the catalog is what you're afraid to touch, you do.

See Also