Home/Learn/System Design/Saga Pattern

Saga Pattern

Advanced
Architectural Patterns

The Saga pattern manages distributed transactions across microservices using a sequence of local transactions with compensating actions for rollback, replacing traditional two-phase commit.

Overview

In a monolith, a single database transaction can span multiple tables atomically. In microservices, each service has its own database, so a single business operation (e.g. placing an order) spans multiple services and their databases. Two-phase commit (2PC) is slow, fragile, and not supported by most NoSQL databases. The Saga pattern breaks a distributed transaction into a sequence of local transactions, each in its own service. If any step fails, previously completed steps are undone by compensating transactions (reverse operations). Two styles exist: Choreography — each service publishes events and listens for events, forming a chain (decentralised, simple for small sagas). Orchestration — a central orchestrator coordinates the saga steps and compensations (centralised, easier to manage complex flows).

Choreography Saga

Each service performs its local transaction and publishes an event. The next service listens for that event and performs its step. On failure, services publish compensation events.

Conceptual + Java — choreography saga
// Choreography saga — order placement
//
// 1. OrderService: create order (PENDING) → emit "OrderCreated"
// 2. PaymentService: listens "OrderCreated" → charge payment → emit "PaymentCompleted"
// 3. InventoryService: listens "PaymentCompleted" → reserve stock → emit "StockReserved"
// 4. OrderService: listens "StockReserved" → update order to CONFIRMED
//
// Failure at step 3 (out of stock):
// 3. InventoryService: emit "StockReservationFailed"
// 2. PaymentService: listens → refund payment → emit "PaymentRefunded"
// 1. OrderService: listens → cancel order → set status to CANCELLED

// Spring Boot choreography implementation
@KafkaListener(topics = "order-created")
public void onOrderCreated(OrderCreatedEvent event) {
    try {
        paymentGateway.charge(event.getUserId(), event.getTotal());
        kafka.send("payment-completed", new PaymentCompletedEvent(event.getOrderId()));
    } catch (PaymentFailedException e) {
        kafka.send("payment-failed", new PaymentFailedEvent(event.getOrderId()));
    }
}

Orchestration Saga

A central orchestrator defines the saga steps and compensation logic. It sends commands to each service and decides the next step based on the response.

Java — orchestration saga with compensation
// Orchestration saga — central coordinator
public class OrderSagaOrchestrator {
    public void executeSaga(PlaceOrderCommand cmd) {
        SagaExecution saga = SagaExecution.start(cmd.getOrderId());
        try {
            // Step 1: Create order
            orderService.createOrder(cmd);
            saga.markStep("CREATE_ORDER");

            // Step 2: Charge payment
            paymentService.charge(cmd.getUserId(), cmd.getTotal());
            saga.markStep("CHARGE_PAYMENT");

            // Step 3: Reserve inventory
            inventoryService.reserve(cmd.getItems());
            saga.markStep("RESERVE_INVENTORY");

            // Step 4: Confirm order
            orderService.confirm(cmd.getOrderId());
        } catch (Exception e) {
            // Compensate in reverse order
            saga.compensate(step -> switch (step) {
                case "RESERVE_INVENTORY" -> inventoryService.release(cmd.getItems());
                case "CHARGE_PAYMENT"    -> paymentService.refund(cmd.getOrderId());
                case "CREATE_ORDER"      -> orderService.cancel(cmd.getOrderId());
            });
        }
    }
}

// Orchestration pros vs choreography:
// ✅ Easier to understand (logic in one place)
// ✅ Better for complex sagas (10+ steps)
// ❌ Orchestrator is a single point of complexity
// ❌ Can become a "god service"

Key Points to Remember

  • 1Saga replaces distributed transactions (2PC) with a sequence of local transactions + compensating actions.
  • 2Choreography: services react to events (decentralised, good for simple sagas).
  • 3Orchestration: central coordinator manages steps (better for complex multi-step sagas).
  • 4Compensating transactions must be idempotent — they may be triggered multiple times.
  • 5Sagas provide eventual consistency, not ACID — design for intermediate states being visible.

Interview Questions

Sign in to ask Aria
1

What is the Saga pattern and why is it needed in microservices?

EasyTCS
2

Compare choreography and orchestration sagas.

MediumAmazon
3

How do compensating transactions work?

MediumGoogle
4

What happens if a compensating transaction itself fails?

HardFlipkart
5

Design a saga for an e-commerce checkout spanning payment, inventory, and shipping.

HardUber

Ask Aria about Saga Pattern

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…