Skip to content

Concept

Choreography vs Orchestration

Two ways to run a saga — peer services reacting to events, or a central orchestrator directing each step.

Once you know saga is a sequence of local transactions, the next question is: who runs that sequence?

There are two types of saga: choreography and orchestration.

Choreography

In choreography, there’s no central boss. Each service publishes success or failure events, and other services proceed after listening to those events.

Think two queues — success and failure. Services publish to them. Services also listen from them. Everyone is both a publisher and a consumer.

Happy path: service updates DB → publishes success → next service listens → updates → publishes success → and so on.

Failure path: payment fails → publishes failure → previous services listen in sequence, roll back, publish failure again → user gets failure.

Same style as the order / inventory / payment walkthrough in Saga Pattern.

Choreography (peers)

Order ──evt──► Inventory ──evt──► Payment
  ▲                 │                │
  └──── failure / rollback events ───┘

The catch with choreography

Circular dependency.

Because every service can publish and listen, you can end up with weird loops. Service A waits on B, B does something that waits on A again, or messages bounce around in a cycle. Once the graph gets messy, this becomes hard to reason about — and hard to debug in interviews and in production.

Orchestration

Orchestration adds a new component: the orchestrator.

That server owns the sequence when a transaction needs multiple microservices to update their databases. Services don’t poke each other with “you go next” events as much. The orchestrator tells them what to do.

Happy path roughly:

  1. Request comes in. Orchestrator takes it.
  2. Tells service A: update yourself.
  3. A succeeds, replies success.
  4. Orchestrator tells service B: update.
  5. Same until the chain is done.

Failure path:

  1. Some service says: I failed.
  2. Orchestrator sends abort / rollback.
  3. Earlier services roll back in a controlled order.
  4. Each confirms rollback.
Orchestration

              ┌──────────────┐
Request ───►  │ Orchestrator │
              └──────┬───────┘
         update │    │ abort
                ▼    ▼
           Order / Inventory / Payment
                │
             success / fail back to orchestrator

The cyclic dependency problem gets removed (or at least pushed into one place you can see), because the flow is explicit in the orchestrator instead of living as a web of peer events.

Who runs the saga?
Order publishes success
choreography — peers drive the next stepOrderpublishing…InventorywaitingPaymentwaitingevent → event → eventno central boss

Order updates DB, publishes event — next peer listens

Peers publish & listen — no central boss. Watch for circular event loops.

Which one do you pick

Choreography is fine when the flow is short and stable — fewer moving parts, no extra orchestrator service.

When there are many steps, lots of failure branches, or you’re already feeling circular event dependencies, orchestration is cleaner. You pay for one more component, but the sequence is easier to explain and control.

In interviews, knowing both names — and when circular dependency shows up in choreography — is usually enough to sound like you’ve actually thought about this.

When not to use which

Don’t start with orchestration for a two-step saga. You’ll build a conductor for a duet.

Don’t stick with pure choreography once you have eight services and five failure branches. You’ll spend more time tracing “who fired what” than shipping features.

Production pitfall

Orchestrator as a silent SPOF. Everyone loves the clean diagram until the orchestrator dies mid-saga and nobody knows which steps committed. Persist saga state (which step succeeded, what’s pending), make commands idempotent, and design for “resume or compensate” after a restart — not “hope the process was still in memory.”