Skip to content

Orchestration vs. Choreography

Orchestration has one conductor telling every player what to do and when; choreography has every player reacting to what the others just did, with no conductor at all.

  • What it is: Two strategies for running a business process that spans multiple systems. Orchestration uses a central coordinator (a workflow engine or saga orchestrator) that calls each system in a defined order and tracks overall state. Choreography has each system independently react to events published by the others, with no central coordinator.
  • Why it matters: Picking the wrong one makes a multi-system process either brittle (a missing central view of what’s happening) or overly rigid (a coordinator that becomes a bottleneck for every change).
  • For developers: if you find yourself asking “wait, who’s actually in charge of this process end-to-end?” and can’t answer in one sentence, that’s usually a sign a choreography-only design needs an orchestrator introduced for at least the steps that need strict sequencing or compensation.
  • When to use it: Orchestration when a process has strict ordering, needs a single place to see overall status, or requires compensating actions on failure. Choreography when steps are independent, loosely coupled, and new participants should be addable without touching existing ones.
  • When not to use it: Don’t add an orchestrator for simple, independent one-way notifications — that’s just Messaging & Event Brokers with unnecessary ceremony.
  • Prerequisites: Messaging & Event Brokers.
graph TD
    subgraph Orchestration
    O[Orchestrator / Saga] --> S1[Step 1: Reserve Stock]
    O --> S2[Step 2: Charge Payment]
    O --> S3[Step 3: Schedule Shipment]
    O -.compensate on failure.-> S1
    end
graph LR
    subgraph Choreography
    E1[Order Placed event] --> W[Warehouse reacts]
    W --> E2[Stock Reserved event]
    E2 --> P[Payment reacts]
    P --> E3[Payment Charged event]
    E3 --> Sh[Shipping reacts]
    end

In orchestration, the coordinator holds the process state and decides the next step. In choreography, the “process” only exists as the sum of each system’s independent reactions — no single place holds the full picture.

  1. List every step of the business process and the system responsible for each.
  2. Check whether failure at any step requires undoing (compensating) earlier steps — if yes, lean toward orchestration.
  3. Check whether the set of participating systems is likely to grow over time without needing to touch existing steps — if yes, lean toward choreography.
  4. For orchestration, choose a workflow/saga engine to own the process state and compensation logic.
  5. For choreography, ensure each event is well-documented (see Messaging & Event Brokers) since there’s no central coordinator to consult.
  6. Mixed processes are normal: orchestrate the steps that need strict sequencing/compensation, and let peripheral systems choreograph off the resulting events.

Building on Messaging & Event Brokers’s InventoryAdjusted event: the wider order-fulfillment process (reserve stock, charge payment, schedule shipment) needs to reliably undo earlier steps if a later one fails — for example, refund the payment if shipment scheduling fails.

  • Input: reserve-stock, charge-payment, and schedule-shipment as three independent choreographed reactions to events, with no way to guarantee a refund happens if shipment scheduling fails.
  • Process: introduce a saga orchestrator for just this core sequence — it calls reserve stock, then charge payment, then schedule shipment, and runs a compensating refund if the last step fails. The storefront and analytics systems continue to choreograph off the resulting events (like the earlier InventoryAdjusted example) since they don’t need compensation logic.
  • Output: the core money-and-inventory sequence gets reliable, centrally visible compensation, while peripheral consumers keep the flexibility of choreography.
[Function(nameof(OrderFulfillmentSaga))]
public async Task RunAsync([OrchestrationTrigger] TaskOrchestrationContext context)
{
await context.CallActivityAsync(nameof(ReserveStock));
try
{
await context.CallActivityAsync(nameof(ChargePayment));
await context.CallActivityAsync(nameof(ScheduleShipment));
}
catch
{
await context.CallActivityAsync(nameof(RefundPayment)); // compensating transaction
throw;
}
}

This saga runs as an Azure Durable Functions orchestration, which persists the process state between steps so “where is order #1234 right now” has a single, queryable answer.

resource sagaStorage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'stfulfillmentsaga'
location: location
kind: 'StorageV2'
sku: { name: 'Standard_LRS' }
}
resource sagaFunctionApp 'Microsoft.Web/sites@2023-12-01' = {
name: 'func-order-fulfillment-saga'
location: location
kind: 'functionapp'
properties: {
siteConfig: {
appSettings: [
{ name: 'AzureWebJobsStorage', value: 'DefaultEndpointsProtocol=https;AccountName=${sagaStorage.name};EndpointSuffix=core.windows.net' }
{ name: 'FUNCTIONS_WORKER_RUNTIME', value: 'dotnet-isolated' }
]
}
}
}

Durable Functions needs its own dedicated Storage Account (stfulfillmentsaga) to persist orchestration state — a small, separate account from whatever stores the application’s actual order data.

Use case Reach for Notes
Multi-step process needs guaranteed rollback on failure Orchestration (saga) Compensating transactions are easiest to reason about with a central coordinator
Independent systems reacting to “something happened,” no rollback needed Choreography New subscribers can be added without touching the process
Need a single dashboard showing “where is order #1234 right now” Orchestration The orchestrator’s state is that single source of truth
Adding a new participant frequently (e.g. new partner integrations) Choreography No orchestrator to modify each time
  • Saga pattern: a sequence of local transactions across systems, each with a corresponding compensating transaction that undoes it if a later step fails.
  • Choreography’s hidden coupling: even without a central coordinator, choreographed systems are still coupled through the event schema — changing an event’s shape is still a breaking change for every subscriber.
  • Hybrid is common: most real processes orchestrate the core transactional path and let non-critical side effects (analytics, notifications) choreograph off the same events.
  • Further reading: ByteByteGo’s Orchestration vs. Choreography in Microservices walks through the same tradeoff with additional real-world examples, useful once this page’s core distinction is clear.
Term Meaning
Orchestration A central coordinator directs each step of a multi-system process
Choreography Each system reacts independently to events, with no central coordinator
Saga A sequence of local transactions with compensating transactions for rollback
Compensating transaction An action that undoes the effect of an earlier step after a later failure
Symptom Likely cause Fix
No one can answer “what state is this order in right now” Pure choreography with no central process view Introduce an orchestrator (or at least a process-tracking read model) for the core path
Every process change requires redeploying a monolithic orchestrator Over-orchestrated design Move independent, non-compensating steps to choreography
A failure leaves stock reserved but payment never charged Missing compensating transaction Add a saga step to release the reservation on downstream failure
  • Why does needing a compensating transaction push a design toward orchestration rather than choreography?
  • In the worked example, why do the storefront and analytics systems stay choreographed instead of being pulled into the orchestrator?

Part of Introduction to Integration Architecture. Builds on Messaging & Event Brokers; see also Resilience & Error Handling in Integration for compensating-transaction failure handling, and the Glossary for term definitions.