Free — no signup required

Saga Compensation: The "Undo" Button

2 min read

What Happens When Things Go Wrong?

In our Saga, what if Steps 1 and 2 succeed, but Step 3 (Payment) fails because the card is declined?

We cannot simply "rollback" the Order and Inventory databases. Those local transactions already committed. Other processes may have read that data. The database has moved on.

Instead, we must execute Compensating Transactions — application-level operations that semantically reverse the effect of a previously committed step.

For every forward action in a Saga, you must design a corresponding compensation:

Step Forward Action Compensating Transaction
1 Create Order (PENDING) Cancel Order (set status: REJECTED)
2 Reserve Stock Release Stock Reservation
3 Charge Card Issue Refund

If Step 3 fails, the Saga executes compensations in reverse order:
1. Step 3 failed — no compensation needed (nothing was charged).
2. Execute compensation for Step 2: Release the stock reservation.
3. Execute compensation for Step 1: Cancel the order.

The system returns to a consistent state: no order, no reserved stock, no charge.

Compensations Are Not Rollbacks

This is a critical distinction. A database rollback undoes changes as if they never happened. A compensating transaction is a new, real business operation that acknowledges the original action happened and explicitly reverses its business effect. An "Order Cancelled" record is created. A "Stock Released" event is published. These are real events in your system's history.

This also means compensations can fail. Your Saga implementation must handle the case where a compensation itself encounters an error — typically by retrying with exponential backoff, alerting an operator, or placing the failed compensation in a dead-letter queue for manual resolution.

Interview Tip

A common interview follow-up is: "What if a compensating transaction fails?" This is where many candidates stumble. The answer is that compensations must be idempotent (safe to retry multiple times with the same result) and retried aggressively. If retries are exhausted, the failure must be surfaced to a human operator — you cannot silently ignore a failed compensation, as it leaves the system in a permanently inconsistent state. This is why observability and alerting around Saga execution are critical.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free