Two opposite ways to coordinate a multi-service workflow — a central controller calling each step, or services independently reacting to each other's events.
A multi-step workflow across services needs its sequence and error-handling defined somewhere. Put it in one place and that place becomes a single dependency everything relies on. Spread it across services reacting to each other's events, and the sequence becomes implicit, readable only by tracing many services' event handlers.
Orchestration (see the dedicated Orchestration page) has one coordinator directly calling each service in sequence and deciding what happens next. Choreography (see the Saga page) has each service publish an event when it finishes, and other services independently subscribe and react — there is no central coordinator at all.
Same two steps, two coordination styles: one function explicitly sequences them; the other lets each step trigger the next through an event.
// Orchestration: one coordinator calls each step directly.
async function orchestratedCheckout() {
await reserveInventory();
await chargePayment();
console.log("orchestrated: checkout complete");
}
// Choreography: each step reacts to an event, no central coordinator.
const bus = new EventTarget();
bus.addEventListener("InventoryReserved", async () => {
await chargePayment();
bus.dispatchEvent(new Event("PaymentCharged"));
});
bus.addEventListener("PaymentCharged", () => console.log("choreographed: checkout complete"));
async function reserveInventory() { console.log("inventory reserved"); }
async function chargePayment() { console.log("payment charged"); }
await orchestratedCheckout();
bus.dispatchEvent(new Event("InventoryReserved")); // kicks off the choreographed chain