Free — no signup required

Coordinating Sagas: Choreography vs. Orchestration

2 min read

How do services know when to execute their step, and who triggers compensations when something fails? There are two architectural approaches, and the choice has significant implications for how your system behaves under failure.

Choreography (Event-Driven)

In choreography, there is no central controller. Services react to events published by other services. Each service knows what events to listen for and what events to emit.

Happy path:
1. OrderService commits its local transaction and publishes OrderCreated.
2. InventoryService listens for OrderCreated, reserves stock, publishes StockReserved.
3. PaymentService listens for StockReserved, charges the card, publishes PaymentProcessed.

Failure path:
1. PaymentService fails and publishes PaymentFailed.
2. InventoryService listens for PaymentFailed and runs its compensation, publishing StockReleased.
3. OrderService listens for StockReleased and runs its compensation.

Pros:
- No single point of failure — no coordinator to crash.
- Services are loosely coupled; adding a new step means adding a new listener.
- Simple to implement for short, linear flows.

Cons:
- The overall business process is implicit — it exists only as a pattern of events across services. There is no single place to look to understand the full flow.
- Debugging failures requires correlating events across multiple services and logs.
- Cyclic event dependencies can emerge as the system grows.

Orchestration (Command-Driven)

A dedicated Saga Orchestrator service explicitly manages the entire workflow. It knows every step, every compensation, and every decision point.

Happy path:
1. Orchestrator sends CreateOrder command to OrderService. Waits for OrderCreated reply.
2. Orchestrator sends ReserveStock command to InventoryService. Waits for StockReserved reply.
3. Orchestrator sends ChargeCard command to PaymentService. Waits for PaymentProcessed reply.

Failure path:
1. PaymentService replies with PaymentFailed.
2. Orchestrator explicitly sends ReleaseStock to InventoryService.
3. Orchestrator explicitly sends CancelOrder to OrderService.
4. Orchestrator marks the Saga as failed and notifies the user.

Pros:
- The entire business process is visible in one place — the orchestrator's state machine.
- Easier to add timeouts, retries, and complex branching logic.
- Simpler to monitor: query the orchestrator to know the state of any in-flight saga.

Cons:
- The orchestrator is a new service to build, deploy, and maintain.
- Services become coupled to the orchestrator's command interface.
- The orchestrator can become a bottleneck if not designed carefully.

When to choose which: For simple, linear flows with 2-3 steps, choreography is often sufficient. For complex business processes with branching logic, timeouts, and many steps, orchestration is almost always the better choice. Tools like Temporal, AWS Step Functions, and Conductor provide orchestration infrastructure so you don't have to build the state machine from scratch.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free