Saga Orchestration vs Choreography Selection Criteria
Guide to selecting Saga patterns for distributed transactions, considering failover, traceability, and team structure

Introduction
In organizations that deal with distributed transactions, the failure model itself changes the moment the Saga pattern is introduced. The problem is that Orchestration and Choreography are often chosen based on technical preference. This article presents practical criteria for choosing between the two models based on team structure, frequency of change, and failure response methods.

Problem definition
If the Saga structure is chosen incorrectly, the recovery time in the exception scenario increases dramatically even though it works in the normal scenario.
- Domain events are expanded indiscriminately, making it impossible to track event flow.
- Compensation transactions are scattered by service, making them highly likely to be missed in the event of a failure.
- MTTR increases as the operations team does not have full flow visibility.
The selection criteria are simple. If the flow is complex and policy changes are frequent, Orchestration is advantageous, and if service independence and loose coupling are more important, Choreography is advantageous.
Key concepts
| perspective | Design criteria | Verification points |
|---|---|---|
| central control | Orchestrator Single Flow Management | Point of Failure Tracking Difficulty |
| distributed autonomy | event-based state transition | Service Independent Deployment Frequency |
| Compensation Strategy | Explicit compensation definition | Missing/duplicate compensation rate |
| Observability | Saga instance-level tracking | Average time to recovery |
You can also select by domain. In practice, a mixed application of Orchestration for flows with complex rules such as payment/settlement and Choreography for notification/analysis pipelines is often used.
Code example 1: Orchestrator state transition
type SagaStep = "reserve" | "pay" | "ship";
export class OrderSagaOrchestrator {
async execute(orderId: string) {
try {
await this.reserveInventory(orderId);
await this.capturePayment(orderId);
await this.requestShipping(orderId);
return { status: "COMPLETED" };
} catch (error) {
await this.compensate(orderId);
return { status: "COMPENSATED", reason: String(error) };
}
}
private async compensate(orderId: string) {
await this.refundPayment(orderId);
await this.releaseInventory(orderId);
}
}
Code example 2: Choreography event consumer
export async function onPaymentCaptured(event: { orderId: string; amount: number }) {
await publish("shipping.requested", { orderId: event.orderId });
}
export async function onShippingFailed(event: { orderId: string }) {
await publish("payment.refund.requested", { orderId: event.orderId });
}
export async function onPaymentRefunded(event: { orderId: string }) {
await publish("inventory.release.requested", { orderId: event.orderId });
}
Architecture flow
Clean Architecture Layer Structure
If Saga is a use case in the application layer and each service call is separated into an adapter layer, it becomes easier to test the compensation logic.
| Layer | responsibility | How to apply |
|---|---|---|
| Entities | Order Status Model | OrderAggregate |
| Use Cases | Saga flow control | ExecuteOrderSaga |
| Interface Adapters | Payment/Inventory port | PaymentGatewayAdapter |
| Frameworks | Message Broker/DB | Kafka, PostgreSQL |
Infrastructure diagram
Tradeoffs
- Orchestration has high flow visibility, but central component failure affects overall throughput.
- Choreography has low coupling, but complexity increases quickly when event schema management fails.
- A mixed strategy is flexible, but incurs onboarding costs as the team must understand both models.
Cleanup
There is not one correct answer to Saga selection. By dividing the model based on domain complexity and operational organization capabilities and fixing the compensation scenario into a testable structure, distributed transaction risk can be greatly reduced.
Image source
- Cover: source link
- License: CC BY-SA 4.0 / Author: Sandra Fauconnier and Alex Stinson
- Note: After downloading the free license image from Wikimedia Commons, it was optimized to JPG at 1600px.