Course contentsShow
← C#
Lesson 1549 of 1,90814. Background Work and MessagingFree lesson

Implementing the Saga Pattern

Orchestrate multi-service operations using state machines to maintain distributed business processes.

In this lesson, you will learn how to maintain data consistency across microservices by using state machines to coordinate long-running distributed business processes.

When a business process spans multiple services—such as an e-commerce order that involves an Inventory Service, Payment Service, and Shipping Service—you cannot rely on traditional database transactions. If one service fails halfway through, you face a distributed data integrity problem. The Saga Pattern solves this by breaking the process into a sequence of local transactions, coordinated by an orchestrator.

Orchestration via State Machines

Instead of having services "fire and forget," an orchestrator maintains a SagaState. This state machine tracks the progress of the workflow. Each step has a corresponding compensation action—a way to undo the changes if a subsequent step fails.

Consider an OrderSaga orchestrating a payment:

public class OrderSaga : SagaStateMachine<OrderState>
{
    public OrderSaga()
    {
        InstanceState(x => x.CurrentState);

        // Define the flow
        Initially(
            When(OrderPlaced)
                .Then(context => context.Saga.OrderId = context.Message.OrderId)
                .TransitionTo(ProcessingPayment)
                .Send(new ProcessPaymentCommand()));

        // Handle failure with compensation
        During(ProcessingPayment,
            When(PaymentFailed)
                .Then(context => UndoInventoryReservation(context))
                .TransitionTo(Cancelled));
    }
}

The orchestrator acts as the "brain." When the PaymentService emits a PaymentFailed event, the Saga intercepts it. Because the orchestrator knows exactly which steps have already completed, it can trigger the UndoInventoryReservation command to revert the system to a consistent state.

Why use State Machines?

By using a state machine, you eliminate "spaghetti" code where every service needs to know about every other service's failure scenarios. The state machine provides:

  1. Visibility: You can query the saga to see exactly where a process is stuck.
  2. Resilience: If a service is down, the saga can retry the message or escalate based on the current state.
  3. Consistency: It guarantees that you eventually reach a terminal state, either Completed or Cancelled, ensuring your distributed system remains in sync without locking databases.

Key Takeaway: The Saga pattern uses state-aware orchestration to manage distributed workflows, ensuring that partial failures are handled by executing explicit compensation logic to maintain system-wide data integrity.