# Saga Pattern

The Saga Pattern is a design pattern for managing data consistency across microservices in distributed transaction scenarios. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga.

## 1. The Problem: Distributed Transactions

In a monolithic application with a single database, you can use **ACID** transactions (Atomicity, Consistency, Isolation, Durability). If you update two tables and the second update fails, the database rolls back the entire transaction automatically.

In a microservices architecture, services have their own private databases. You cannot use a standard database transaction that spans multiple services.
*   **Scenario:** An e-commerce "Checkout" involves:
    1.  `Order Service`: Create order.
    2.  `Inventory Service`: Reserve items.
    3.  `Payment Service`: Charge credit card.
*   **Failure:** If the Payment fails, you must undo the Inventory reservation and cancel the Order.

## 2. The Solution: Compensating Transactions

Since we can't rely on database rollbacks, we must implement **Compensating Transactions**.
*   If a step fails, the saga executes a series of compensating steps that undo the changes made by the preceding steps.

**Example:**
*   **Transaction:** `ReserveInventory()`
*   **Compensation:** `ReleaseInventory()`

## 3. Implementation Approaches

### Choreography (Event-Based)
There is no central coordinator. Each service produces and listens to events to decide on an action.
*   **Flow:**
    1.  `Order Service` creates order -> Emits `OrderCreated`.
    2.  `Inventory Service` hears `OrderCreated` -> Reserves items -> Emits `InventoryReserved`.
    3.  `Payment Service` hears `InventoryReserved` -> Charges card -> Emits `PaymentProcessed`.
*   **Pros:** Simple, loose coupling.
*   **Cons:** Hard to track the workflow (who listens to what?), cyclic dependencies risk.

### Orchestration (Command-Based)
A central coordinator (Orchestrator) tells the participants what local transactions to execute.
*   **Flow:**
    1.  `Order Service` (Orchestrator) tells `Inventory Service`: "Reserve items".
    2.  `Inventory Service` replies: "Done".
    3.  `Order Service` tells `Payment Service`: "Charge card".
*   **Pros:** Centralized logic, easy to understand the flow.
*   **Cons:** The orchestrator can become a "God Service" with too much logic.

## 4. Pros and Cons

| Pros | Cons |
| :--- | :--- |
| **Data Consistency:** Maintains consistency across services without distributed locking (2PC). | **Complexity:** Much more complex to implement and debug than ACID transactions. |
| **Performance:** Better performance than Two-Phase Commit (2PC) because it avoids locking resources. | **Eventual Consistency:** Data is not consistent immediately. Users might see "Pending" states. |
| | **Compensating Logic:** Writing undo logic for every action is tedious and error-prone. |

## 5. Two-Phase Commit (2PC)

Two-Phase Commit (2PC) is an alternative to Sagas for handling distributed transactions. It provides strong consistency (ACID) rather than eventual consistency.

### How it Works
1.  **Prepare Phase:** The transaction coordinator asks all participants if they are ready to commit. Participants lock the necessary resources and vote "Yes" or "No".
2.  **Commit Phase:**
    *   If **all** participants voted "Yes", the coordinator sends a "Commit" command.
    *   If **any** participant voted "No" (or timed out), the coordinator sends a "Rollback" command.

### Why Sagas are often preferred over 2PC
*   **Blocking:** In 2PC, resources are locked from the Prepare phase until the Commit phase completes. If the coordinator fails, resources remain locked. Sagas do not hold locks across services.
*   **Performance:** 2PC is chatty and slow. Sagas are asynchronous and non-blocking.
*   **Scalability:** 2PC scales poorly in distributed systems due to locking.

## 6. Compensating Transaction Pattern

A compensating transaction is an operation that undoes the effect of a previously committed transaction. It is the "undo" button for distributed systems.

### Key Characteristics
*   **Idempotent:** It must be safe to retry the compensation multiple times. If the system crashes while compensating, it will try again upon restart.
*   **Not a Perfect Undo:** It might not restore the system to the *exact* previous state. For example, if you booked a seat and then cancelled it, the seat is free again, but the history shows a booking and a cancellation.

### Handling Failures
What happens if the compensating transaction itself fails?
*   **Retry:** The standard approach is to retry indefinitely until it succeeds.
*   **Manual Intervention:** If it fails permanently (e.g., due to a bug), a human operator must intervene to fix the data consistency.

[[programming/microservices-architecture]]
[[programming/event-driven-architecture]]
[[programming/database-basics]]