Saga Choreography
A saga implementation where each service listens for events and decides what to do next independently. No central coordinator. Looser coupling but harder to trace.
What is Saga Choreography?
In short
Saga choreography is a way to manage a distributed transaction across microservices where each service does its local work, publishes an event, and the next service reacts to that event on its own. There is no central coordinator. Services agree on the flow only through the events they emit and subscribe to.
What it is
A saga is a sequence of local transactions that together make up one business operation spanning several services, like placing an order that touches Orders, Payments, Inventory, and Shipping. Each step commits to its own database. There is no shared database transaction and no two-phase commit, so the saga keeps consistency by running compensating actions when a later step fails.
Choreography is one of the two ways to run a saga. The other is orchestration, where a single coordinator tells each service what to do. In choreography there is no coordinator. Each service listens for events on a message bus, does its part, and publishes a new event that some other service is waiting for. The workflow is an emergent property of who subscribes to what.
The short version: orchestration is a conductor telling musicians when to play, choreography is dancers who each know their cue from the dancer next to them.
How it works under the hood
It runs on an event broker such as Kafka, RabbitMQ, or AWS SNS plus SQS. The first service commits its local transaction and publishes a domain event, for example OrderCreated. Payments subscribes to OrderCreated, charges the card, and publishes PaymentCompleted. Inventory subscribes to PaymentCompleted, reserves stock, and publishes StockReserved, and so on down the chain.
Failures are handled by compensating events flowing backward. If Inventory cannot reserve stock it publishes StockReservationFailed. Payments subscribes to that and issues a refund, then publishes PaymentRefunded, which the Orders service uses to mark the order canceled. Each service owns both its forward action and its undo action.
Two properties make this safe in practice. Events must be delivered reliably, usually with the transactional outbox pattern so the database write and the event publish cannot diverge. And every handler must be idempotent, because at-least-once brokers will redeliver, so charging the same OrderCreated twice has to be a no-op the second time. Correlation IDs on every event let you stitch the steps back together for debugging.
When to use it and the trade-offs
Choreography fits short sagas with a small number of participants, maybe two to four services, where the flow is simple and unlikely to grow complicated. Because there is no central service to deploy and own, it keeps services loosely coupled and each team can change its own logic without coordinating with a workflow owner.
The cost is that nobody can see the whole flow in one place. The business process is spread across the subscriptions of every service, so understanding what happens after OrderCreated means tracing events through five codebases. Cyclic dependencies sneak in easily, and a small change to one event can break a downstream service that you forgot subscribes to it.
Switch to orchestration once the saga has many steps, branching logic, or timeouts and retries you want to manage centrally. A common rule of thumb: use choreography while the flow stays linear and simple, move to an orchestrator like Temporal, AWS Step Functions, or a dedicated saga service once you need to ask one component what state the transaction is in.
A concrete example
Picture an e-commerce checkout. The Order service writes the order as PENDING and publishes OrderCreated to a Kafka topic. The Payment service consumes it, charges the customer through Stripe, and publishes PaymentCompleted. The Inventory service consumes that, decrements stock, and publishes StockReserved. Finally the Shipping service consumes StockReserved and schedules a courier, publishing OrderConfirmed, which flips the order to CONFIRMED.
Now suppose inventory is out of stock. Inventory publishes StockReservationFailed instead. Payment hears it and refunds the Stripe charge, publishing PaymentRefunded. Order hears that and moves the order to CANCELED. The customer is made whole without any single service having known the full plan in advance. Each one only knew its own cue.
Where it is used in production
Apache Kafka
The most common backbone for choreographed sagas, with each service consuming and producing domain events on topics.
Netflix
Uses event-driven choreography across services for workflows like content onboarding, with services reacting to each other's events rather than a single controller.
AWS (SNS + SQS)
A standard serverless setup where Lambda functions subscribe to topics and queues to react to events and emit the next step of a saga.
RabbitMQ
Used as the broker for choreographed sagas in many enterprise systems, routing events between services through exchanges and queues.
Frequently asked questions
- What is the difference between saga choreography and orchestration?
- In orchestration a single coordinator service tells each participant what to do and tracks the overall state. In choreography there is no coordinator: each service reacts to events and publishes its own, so the flow is distributed across all participants. Orchestration is easier to monitor, choreography is more loosely coupled.
- How does choreography handle a failure midway through?
- Through compensating actions. When a step fails it publishes a failure event, and the services that ran earlier steps subscribe to it and undo their work, for example refunding a payment or releasing reserved stock. The undo events flow backward through the chain until the saga is fully rolled back.
- Why must event handlers be idempotent in a choreographed saga?
- Most message brokers deliver at least once, so the same event can be redelivered. If charging a card or reserving stock ran twice it would corrupt state, so each handler must detect a duplicate, often by recording the processed event or correlation ID, and treat the repeat as a no-op.
- When should I avoid choreography?
- Avoid it when the saga has many participants, branching logic, or timeouts you need to manage centrally. As the number of event subscriptions grows the flow becomes hard to follow and cyclic dependencies appear. At that point an orchestrator gives you one place to see and control the transaction.
- Does choreography need a distributed transaction or two-phase commit?
- No. That is the whole point of the saga pattern. Each service commits only its own local transaction, and global consistency is reached eventually through events and compensations rather than locking resources across services with two-phase commit.
Learn Saga Choreography hands-on
This page explains the idea. The full lesson lets you step through the ring as servers join and leave, read the implementation, and check yourself with a quiz. It is one of 760+ lessons in the System Design Masterclass, from your first API call to distributed consensus. Eleven Foundation lessons are free, no signup. Lifetime access is ₹499 in India or $7.99 worldwide, one payment, no subscription.
See also
Related glossary terms you might want to look up next.
Saga Pattern
A way to manage distributed transactions across microservices using a sequence of local transactions with compensating actions for rollback.
Saga Orchestration
A saga implementation where a central orchestrator tells each service what step to execute next. Easier to debug than choreography but creates a single point of coordination.
Event-Driven Architecture
A design pattern where services communicate by producing and consuming events rather than making direct calls. Promotes loose coupling and asynchronous processing.
Microservices
An architecture where an application is split into small, independent services that communicate over the network. Each service owns its own data and can be deployed separately.
Monolith
A single, unified application where all features share the same codebase and deployment. Simpler to start with but harder to scale individual parts.
Service Discovery
The mechanism by which microservices find and communicate with each other. Services register themselves and others can look them up by name.