System DesignMedium
SAGA Choreography vs Orchestration — which one should you choose?
Both implement the SAGA pattern but differ in who coordinates the workflow.
Choreography — event-driven, decentralized
Each service publishes events. Other services listen and react. No central coordinator.
// Order service
await _bus.PublishAsync(new OrderPlaced(orderId)); // and we're done
// Inventory service (separate codebase)
public async Task Handle(OrderPlaced ev) {
await ReserveAsync(ev.OrderId);
await _bus.PublishAsync(new StockReserved(ev.OrderId));
}
// Payment service (separate codebase)
public async Task Handle(StockReserved ev) { ... }
Orchestration — central coordinator
A dedicated orchestrator (often a state machine) sends commands and tracks state.
public class OrderSagaOrchestrator {
public async Task RunAsync(PlaceOrder cmd) {
await _inventory.ReserveAsync(cmd.OrderId, cmd.Items);
try {
await _payment.ChargeAsync(cmd.OrderId, cmd.Total);
await _shipping.ScheduleAsync(cmd.OrderId);
} catch {
await _inventory.ReleaseAsync(cmd.OrderId, cmd.Items);
throw;
}
}
}
Side-by-side
| Choreography | Orchestration | |
|---|---|---|
| Workflow visibility | Low — distributed across N services | High — single state machine |
| Coupling | Loose (services know events) | Tighter (orchestrator knows everyone) |
| Tracing failures | Read N service logs | Read one timeline |
| Adding a step | Subscribe new service to existing events | Edit the state machine |
| Best for | 2-3 step, stable workflows | 4+ step, evolving workflows |
| Risk | Spaghetti at scale | Central bottleneck |
Decision rule
Start with Choreography for 2-3 step workflows where the steps don't change often. Move to Orchestration the moment the workflow has 4+ steps OR business rules around the workflow change frequently.
Hybrid
In practice large systems use both:
- Choreography for fire-and-forget side effects (analytics, search indexing, notifications)
- Orchestration for the core business workflow (order, payment, fulfilment)
Tooling
- Choreography: Kafka, RabbitMQ, MassTransit
- Orchestration: Temporal.io, Camunda, MassTransit Saga, AWS Step Functions, Azure Durable Functions
For .NET specifically, MassTransit's saga state machine is the standard orchestration choice; for cross-language workflows, Temporal is the strongest option.