Skip to content

Saga basics

Saga — Full Revision Summary


What is it?

A pattern for managing transactions that span multiple microservices, where each service has its own database and a single DB transaction is impossible.

Core idea: Break the transaction into sequential steps. Define a compensating action for every step. If anything fails, execute compensations in reverse order.


The two approaches:

Choreography

No central controller. Services react to events and know what to listen to.

Each service:
- Publishes what it did       ("PaymentCharged")
- Listens for failure events  ("StockDeductionFailed")
- Knows its own compensation  (refund if stock failed)

Pros: Simple, no extra infrastructure, loosely coupled.

Cons: Flow is spread across services, hard to follow, hard to debug as it grows.


Orchestration

A central orchestrator owns the flow. It consumes result events and issues commands.

Orchestrator:
- Listens to result events    ("PaymentCharged", "StockDeductionFailed")
- Issues commands             ("ChargePayment", "RefundPayment")
- Tracks saga state in a DB row per saga instance

The individual services have no idea they're part of a saga — they just receive a command, do their job, publish a result.

Pros: Flow is visible in one place, easier to debug, handles complex scenarios.

Cons: Extra service to maintain, orchestrator can be a single point of failure.


The Saga State Machine (Orchestration only):

Every saga instance has a row in a DB table tracking its current state and what steps completed.

| CorrelationId | CurrentState     | PaymentCharged | StockDeducted |
|---------------|------------------|----------------|---------------|
| abc-123       | Compensating     | true           | false         |

This gives the orchestrator memory — critical for knowing what to compensate after a crash or out-of-order events.


How RabbitMQ fits in:

RabbitMQ is just the transport. Every participant including the orchestrator is just a publisher and consumer with its own queue. Nobody blocks waiting for responses — everything is fire and forget, responses come back as separate messages.


What makes Saga reliable in practice:

  • Outbox pattern — events are never lost even if service crashes after DB write
  • Idempotency — retries don't cause duplicate actions
  • State tracking — always know where the saga is, survive crashes

The trade-off to always mention:

Saga gives you eventual consistency, not strong consistency. There's a window where data is partially updated across services. That's the accepted trade-off in microservices.


One line summary:

"Saga manages cross-service transactions by defining steps with compensating actions, coordinated either via events between services (choreography) or a central orchestrator, ensuring the system can always cleanly undo partial work on failure."