Implementing Saga Patterns
1. Saga Orchestration Pattern
| Aspect | Detail |
| Definition | Central orchestrator drives steps; tells each service what to do |
| State | Held by orchestrator (durable workflow state) |
| Pros | Visible flow; easier debugging; explicit compensation |
| Cons | Orchestrator can become god-service if logic creeps in |
| Tools | Camunda, Temporal, AWS Step Functions, Axon |
Example: Order Saga Orchestrator (Temporal-style)
public class OrderSaga {
public void run(OrderRequest req) {
try {
payment.charge(req);
inventory.reserve(req);
shipping.schedule(req);
order.markConfirmed(req.orderId());
} catch (Exception ex) {
shipping.cancel(req.orderId());
inventory.release(req.orderId());
payment.refund(req.orderId());
order.markFailed(req.orderId(), ex.getMessage());
}
}
}
2. Saga Choreography Pattern
| Aspect | Detail |
| Definition | Each service reacts to events; no central coordinator |
| Flow | Emerges from event subscriptions |
| Pros | Loose coupling; easy to add reactors |
| Cons | Hard to see end-to-end; cyclic dependencies risk |
Choreography Flow
OrderPlaced → Payment reacts → PaymentCharged → Inventory reacts → InventoryReserved → Shipping reacts → Shipped
↓ (fail)
PaymentFailed → Order reacts → OrderCancelled
3. Implementing Compensating Transactions
| Property | Requirement |
| Semantically Reverses | Undoes business effect (refund instead of "delete payment") |
| Idempotent | Must be safe to retry |
| Best Effort | May not perfectly restore state (e.g., email already sent) |
| Logged | Audit trail of compensation |
| Forward Action | Compensation |
| Charge payment | Refund payment |
| Reserve inventory | Release reservation |
| Send email | Send "ignore previous" email |
| Schedule shipment | Cancel shipment |
4. Managing Saga State Machines
| State | Description |
| STARTED | Saga initiated |
| PAYMENT_CHARGED | Payment step done |
| INVENTORY_RESERVED | Stock reserved |
| SHIPPED | Item dispatched |
| COMPLETED | Saga succeeded |
| COMPENSATING | Rolling back |
| FAILED | Compensated; saga ended in failure |
5. Handling Saga Failures
| Failure Type | Handling |
| Transient | Retry with backoff; don't compensate yet |
| Business Rule | Compensate prior steps; mark FAILED |
| Permanent (4xx) | No retry; immediate compensation |
| Compensation Failure | Alert + manual intervention queue |
6. Saga Timeout Pattern
| Aspect | Detail |
| Per-Step Timeout | Cap each activity (e.g., 30s) |
| Saga-Wide Timeout | Total deadline (e.g., 24h for order) |
| Action | Trigger compensation on timeout |
| Tools | Temporal timers, Camunda BPMN timers |
7. Saga Recovery Pattern
| Trigger | Recovery |
| Orchestrator Crash | Resume from last persisted state |
| Service Down | Retry with exponential backoff |
| Stuck Saga | Operator console: retry / abort / skip step |
| Data Loss | Replay from saga event log |
8. Saga Isolation Pattern
| Countermeasure | Detail |
| Semantic Lock | Mark record as "in-saga" (e.g., status=PENDING) to block other ops |
| Commutative Updates | Order-independent ops (additive) |
| Pessimistic View | Hide partially-committed state from queries |
| Re-read Value | Verify assumptions before each step |
| Version File | Track concurrent updates |
Warning: Sagas are NOT ACID — they have no isolation by default. Lack of isolation can show partial state to other transactions.
9. Saga Logging Pattern
| Logged Item | Purpose |
| Saga ID + Correlation ID | Trace across services |
| Step Started/Completed | Forensics, dashboards |
| Compensation Attempts | Audit, debugging |
| Final Outcome | SLA reporting |
10. Saga Compensation Order Pattern
| Rule | Detail |
| LIFO Order | Compensate in reverse of forward steps |
| Skip Untaken Steps | Only compensate steps that succeeded |
| Persistent Plan | Compensation plan stored before forward execution |
| Continue on Compensation Fail | Try all compensations; flag failures separately |