Saga

Coordinates long-running transactions across services using steps and compensations.

Context

A business process spans multiple services (Payment, Inventory, Shipping). Distributed transactions (2PC) do not scale.

Problem

Without a coordinator, there's no way to roll back partial steps if something fails halfway through.

Solution

The Saga executes a sequence of local steps. If one fails, it executes its compensations in reverse order.

#Variants

  • Orchestrated: A central coordinator dictates each step.
  • Choreographed: Each service reacts to events from others.

#C# Example — Orchestrated Saga

public class PlaceOrderSaga
{
    public async Task RunAsync(PlaceOrderCommand cmd)
    {
        var orderId = await _orders.CreateAsync(cmd);
        try
        {
            await _payments.ChargeAsync(orderId, cmd.Total);
            await _inventory.ReserveAsync(orderId, cmd.Items);
            await _shipping.ScheduleAsync(orderId);
        }
        catch
        {
            // Compensations in reverse order
            await _shipping.CancelAsync(orderId);
            await _inventory.ReleaseAsync(orderId);
            await _payments.RefundAsync(orderId);
            await _orders.MarkFailedAsync(orderId);
            throw;
        }
    }
}
Tradeoffs
Pro Con
No distributed transactions Each step requires its compensation
Saga state is persistent and resumeable Designing idempotent compensations is difficult

#extra #distributed #transaction