The saga pattern coordinates multi-step distributed transactions by breaking them into a sequence of local transactions with compensating actions for rollback. What the saga post didn’t cover: there are two fundamentally different ways to implement coordination, and choosing between them shapes your entire system architecture.

Choreography: Services React to Events#

In choreography, there is no central coordinator. Each service listens for events and reacts by doing its part and publishing its own events.

Order saga via choreography:

  1. Order service creates order, publishes OrderCreated event
  2. Inventory service listens for OrderCreated, reserves stock, publishes StockReserved
  3. Payment service listens for StockReserved, charges card, publishes PaymentCompleted
  4. Shipping service listens for PaymentCompleted, arranges delivery

If payment fails, the payment service publishes PaymentFailed. The inventory service listens for that event and releases the reserved stock.

No single service knows the full workflow. Each knows its own step and what event triggers it.

Orchestration: A Coordinator Directs#

In orchestration, a central orchestrator service explicitly tells each service what to do and waits for responses.

Orchestrator:
  1. Call inventory service: reserve stock for order 101
  2. Wait for response
  3. Call payment service: charge $49.99 for order 101
  4. If payment fails:
       Call inventory service: release stock for order 101
  5. If payment succeeds:
       Call shipping service: arrange delivery for order 101

The orchestrator holds the workflow state and makes decisions. Other services are just workers that execute instructions.

graph TD A[Choreography: Event-driven] --> B[Order Service publishes OrderCreated] B --> C[Inventory Service reacts, publishes StockReserved] C --> D[Payment Service reacts, publishes PaymentCompleted] E[Orchestration: Explicit coordination] --> F[Saga Orchestrator calls Inventory Service] F --> G[Orchestrator calls Payment Service] G --> H[Orchestrator calls Shipping Service] style A fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style B fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style C fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style D fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style E fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style F fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style G fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style H fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff

The Trade-Offs#

Choreography advantages: no single point of failure, services are loosely coupled, easy to add new steps without changing existing services.

Choreography disadvantages: workflow logic is distributed across many services. Debugging requires tracing events across multiple services. It’s hard to answer “what is the current state of order 101?” without querying multiple services.

Orchestration advantages: workflow is visible in one place, easy to monitor and debug, clear ownership of business logic.

Orchestration disadvantages: the orchestrator is a new service that must be reliable, creates coupling between the orchestrator and all workflow participants, harder to evolve independently.

At Salesforce#

We had an onboarding workflow for new orgs: provision database, configure defaults, send welcome email, notify billing. Initially done as a sequence of service calls in a single HTTP request handler. This was brittle: any step failure failed the entire request. We moved to an event-driven approach (choreography), where each step published completion events and the next step listened. Debugging became harder (“where did the onboarding get stuck for org 87654?”), but reliability improved significantly. We eventually added a workflow tracking table to answer the “where is it stuck?” question without giving up the loose coupling.

What I’m Learning#

Neither approach is universally better. Choreography fits systems that are already event-driven and where services should remain independent. Orchestration fits workflows where you need clear visibility, complex branching logic, or a single team owns the whole workflow. Many mature systems use both: choreography for asynchronous event flows, orchestration for synchronous multi-step processes.

Do you use choreography, orchestration, or a mix at your company, and what drove that choice?