Saga Pattern
- In Turkish
- Saga Deseni
In short
The saga pattern runs a transaction spanning several services as a sequence of local steps, undoing completed steps with compensating actions if one fails.
What is the saga pattern?
In a microservices system, each service usually owns its own database, so a single business action, like placing an order, may need to update data in several services. A normal database transaction can't cover all of them, and distributed locking protocols such as two-phase commit are slow and fragile at scale. The saga pattern solves this by breaking the action into a sequence of local transactions, one per service, each of which commits on its own.
If every step succeeds, the saga is complete. If a step fails, the saga runs compensating transactions for the steps that already finished, in reverse order, to undo their effects, such as releasing reserved stock or refunding a payment. A saga can be coordinated in two ways: with orchestration, a central orchestrator tells each service what to do next, while with choreography each service listens for events from the others and reacts, with no central controller. Because messages may be delivered more than once, each step and compensation should be idempotent.
Booking a trip is the classic analogy. You book a flight, then a hotel, then a rental car; if no car is available, you cancel the hotel and the flight rather than pretending the whole trip never happened. Sagas are used for order processing, payments, travel and ticket booking, and any workflow that crosses service boundaries, and the idea dates back to a 1987 database paper on long-lived transactions.
A saga is often confused with an ACID transaction, but it offers weaker guarantees. There is no isolation: other requests can see intermediate states, such as an order that is paid but not yet confirmed, so the system is eventually consistent rather than instantly consistent. Compensation is also not a true rollback; it is a new business action, and a sent email or a charged card can only be corrected, not erased.
Key takeaways
- A saga splits a cross-service transaction into local steps that commit independently.
- If a step fails, compensating transactions undo the earlier steps in reverse order.
- Orchestration uses a central coordinator; choreography uses events between services.
- Sagas give eventual consistency, not the isolation of an ACID transaction.
- Steps and compensations should be idempotent because messages can repeat.
Example
// Orchestrated saga: run each step, and undo finished steps if one fails
const steps = [
{ run: () => orders.create(order), undo: () => orders.cancel(order.id) },
{ run: () => payments.charge(order), undo: () => payments.refund(order.id) },
{ run: () => stock.reserve(order), undo: () => stock.release(order.id) },
];
async function placeOrder() {
const done: typeof steps = [];
try {
for (const step of steps) { await step.run(); done.push(step); }
} catch (err) {
for (const step of done.reverse()) await step.undo(); // compensate in reverse
throw err;
}
}Readers ask
What is the difference between orchestration and choreography in sagas?
In orchestration, a central orchestrator decides which step runs next and calls each service. In choreography, services publish and listen to events and each one knows what to do when a certain event arrives; this avoids a central coordinator but makes the overall flow harder to follow.
What is a compensating transaction?
A compensating transaction is an action that undoes the business effect of an earlier step, such as issuing a refund for a payment or releasing reserved stock. It doesn't erase history; it records a new change that cancels out the old one.
Why not use two-phase commit instead of a saga?
Two-phase commit locks resources in every participating database until all of them agree, which hurts availability and performance and is poorly supported by many modern databases and message brokers. Sagas avoid long locks at the cost of weaker consistency.
See also
- MicroservicesSoftware Architecture, p. 27Microservices are an architectural style where an application is split into small, independently deployable services that communicate over a network.
- TransactionDatabases, p. 47A transaction is a group of database operations that succeed or fail as a single unit, so the data is never left in a half-finished, inconsistent state.
- Eventual ConsistencyDatabases, p. 19Eventual consistency is a guarantee that, if no new updates are made, all copies of a piece of data in a distributed system will become identical over time.
- Event-Driven ArchitectureSoftware Architecture, p. 18Event-driven architecture is a software design style in which services communicate by producing and reacting to events, such as an order being placed.
- IdempotencyBackend & APIs, p. 24Idempotency is the property of an operation that produces the same result whether it runs once or many times, so accidentally repeating a request is safe.
- ACIDDatabases, p. 1ACID is a set of four guarantees, atomicity, consistency, isolation, and durability, that keep database transactions reliable even when errors or crashes occur.
Spotted a mistake or something missing on this page?Suggest an edit