Saga Pattern Explained: Managing Distributed Transactions
In monolithic applications, database transactions are simple: either everything succeeds, or everything rolls back (ACID). But in microservices architecture, each service has its own database. How do you manage a transaction that spans multiple services?
The Problem: Distributed Transactions
Consider an e-commerce order flow:
1. Order Service → Create order
2. Payment Service → Process payment
3. Inventory Service → Decrease stock
4. Shipping Service → Initiate shipping
What if stock is insufficient at step 3? Payment has been processed, the order has been created. These need to be reversed — but each service has a separate database!
The Saga Solution
The Saga Pattern breaks a long-running business process into small, local transactions. Each step either succeeds or triggers a compensating action.
Success flow:
T1 → T2 → T3 → T4 → ✅ Completed
Failure at T3:
T1 → T2 → T3 ❌ → C2 → C1 → ❌ Rolled back
- T = Transaction (forward step)
- C = Compensating action (rollback)
Two Approaches
1. Choreography
Each service publishes events, other services listen and react:
Order Service: OrderCreated →
Payment Service (listens): PaymentProcessed →
Inventory Service (listens): StockDecreased →
Shipping Service (listens): ShippingInitiated
On failure:
Inventory Service: InsufficientStock →
Payment Service: PaymentRefunded →
Order Service: OrderCancelled
Pros: Simple, no central control, loosely coupled Cons: Hard to trace flow, debug difficulty, circular dependency risk
2. Orchestration
A central Saga Orchestrator manages the entire flow:
Saga Orchestrator:
1. → Order Service: "Create order" → ✅
2. → Payment Service: "Process payment" → ✅
3. → Inventory Service: "Decrease stock" → ❌
4. → Payment Service: "Refund payment" (compensation)
5. → Order Service: "Cancel order" (compensation)
Pros: Clear flow, easy debugging, manages complex workflows Cons: Central point of failure risk, tighter coupling
Which Approach?
| Criteria | Choreography | Orchestration | |----------|-------------|---------------| | Steps | 2-4 steps | 5+ steps | | Complexity | Low | High | | Service independence | High | Medium | | Observability | Difficult | Easy | | Adding steps | Easy | Requires orchestrator update |
Compensating Actions
Every transaction must have a compensation:
| Transaction | Compensating Action | |-------------|-------------------| | Create order | Cancel order | | Process payment | Refund payment | | Decrease stock | Restore stock | | Initiate shipping | Cancel shipping |
Key Considerations
- Compensations must be idempotent (safe to run multiple times)
- Some actions can't be reversed (email sent) — design alternative compensations
- Add timeout mechanisms
Saga vs 2PC
| Feature | 2PC (Two-Phase Commit) | Saga Pattern | |---------|----------------------|-------------| | Consistency | Strong | Eventual | | Performance | Slow (locking) | Fast (no locks) | | Scalability | Low | High | | Complexity | Medium | High (compensation logic) | | Best for | Monolithic | Microservices |
Conclusion
The Saga Pattern is the standard solution for managing distributed transactions in microservices architecture. Use Choreography for simple flows and Orchestration for complex ones.
Learn the Saga Pattern and distributed system patterns on the Architect career path at LabLudus. The Software Architecture 3.0 book covers this topic in depth.