Choreography vs orchestration
Placing an order touches several services: Inventory reserves stock, Payments takes the money, Shipping books the delivery. Someone has to make those steps happen in the right order. In choreography nobody does: each service reacts to the events of the others. In orchestration one component, the orchestrator, holds the workflow and tells each service what to do next.
Choreography
Orders publishes OrderPlaced. Inventory reacts and publishes StockReserved. Payments reacts to that and publishes PaymentReceived, and Shipping reacts to that. Every step is an eventEvents, commands and queriesThree kinds of message: an event states a fact, a command asks one owner to act, a query only reads.Opens in a new tab that any service may subscribe to.
There is no coordinator to fail and no central code to change. Adding a consumer, for example Notifications reacting to PaymentReceived, touches nothing else. The cost is that the workflow is written down nowhere. To learn what happens after an order is placed, you read the subscriptions of every service. Microsoft’s saga guidance lists the same drawbacks: it is hard to see which events each participant responds to, new steps make the flow confusing, services can end up depending on each other in a cycle, and testing needs all of them running.
Orchestration
The orchestrator sends a command to one service, waits for the reply event, and then sends the next. It keeps the state of each order’s workflow: which step it is on, and what has succeeded.
Now the whole flow is in one place, which makes it easy to read, to test, and to change. Services stay simple, because each one only handles its own commands. The orchestrator is also a component that can fail or become a bottleneck, it is coupled to every service it calls, and its state must survive a restart. Libraries such as NServiceBus and MassTransit provide saga support for holding that state.
| Aspect | Choreography | Orchestration |
|---|---|---|
| Who knows the whole flow | No one | The orchestrator |
| What services exchange | Events | Commands and reply events |
| Adding a step | Add a subscriber, but the flow becomes harder to follow | Change the orchestrator |
| Seeing where one order is | Join the logs of every service | Read the orchestrator state |
| Single point of failure | None added | The orchestrator |
| Fits | Few services, simple flows | Many steps, branches, failure handling |
Choosing
Start with choreography for two or three steps and no failure path. Move to an orchestrator when the flow has branches, when it needs a timeout or a retry decision, or when someone has to answer “where is order 4711?”. Either one can be used to run a sagaSagasA workflow made of local transactions, with an undo step for each one.Opens in a new tab, which adds the undo steps for a failure partway through. Both rely on the reliability basics: idempotent consumersIdempotent consumersA consumer that gives the same result whether a message arrives once or five times.Opens in a new tab and a way to correlate every message with its order (see traceabilityTraceabilityLog the whole reasoning trace, so any answer can be explained afterwards.Opens in a new tab).
Sources
- Saga Design Pattern, Azure Architecture Center, Microsoft Learn · accessed June 12, 2026
- Event-Driven Architecture Style, Azure Architecture Center, Microsoft Learn · accessed June 12, 2026
- Pattern: Saga, microservices.io · accessed June 12, 2026