Flow Studio
Saga / Compensation Pattern
Using process nodes to implement distributed transaction compensation — starting child workflows and cancelling/reversing them if the overall transaction fails.
The Saga Problem
A distributed business transaction spans multiple independent workflows (e.g., reserve inventory, charge payment, trigger shipment). If the payment fails after inventory is reserved, the reservation must be reversed. This is the saga compensation pattern.
Pattern Structure
Orchestrator Workflow
│
├── StartWorkflow (reserveInventory) ──→ executionId: inv-exec-001
│
├── StartWorkflow (chargePayment) ──→ executionId: pay-exec-002
│ │
│ └── [error] ──→ CompensationPath:
│ CancelWorkflow (inv-exec-001) // cancel inventory reservation
│ StartWorkflow (reversePaymentAttempt) // if partially charged
│ SendEmail (failure notification)
│ EndNode (failed)
│
└── StartWorkflow (triggerShipment)
│
└── [all succeeded] → SendEmail (success confirmation) → EndNode (completed)
Key Design Rules
| Rule | Why |
|---|---|
| Record executionId of every child workflow immediately after starting | You need it to cancel/compensate later |
| Each child workflow should be idempotent | Cancellation signals may arrive after partial completion |
| Compensation workflows should not fail | A failed compensation is worse than the original failure — use retries and alerting |
| Store executionIds in an entity record | If the orchestrator itself fails, the execution IDs survive in persistent storage for manual recovery |
No distributed ACID: Sagas do not provide ACID guarantees across workflows. Compensation logic must handle partial states (e.g., inventory reserved but payment partially processed). Design each step to be reversible and test compensation paths explicitly.