Embracing Eventual Consistency
The Saga Pattern starts from a different premise: instead of trying to make multiple databases behave like one, we accept that they are independent and design our business processes accordingly.
A Saga is a sequence of local transactions, each executed within a single service's own database. Each step commits immediately and independently. There are no global locks, no coordinator holding everyone in suspense.
For our e-commerce checkout:
| Step | Service | Local Transaction | Trigger |
|---|---|---|---|
| 1 | OrderService |
Create order (status: PENDING) | User clicks "Buy" |
| 2 | InventoryService |
Reserve stock | Step 1 succeeds |
| 3 | PaymentService |
Charge credit card | Step 2 succeeds |
| 4 | OrderService |
Update order (status: CONFIRMED) | Step 3 succeeds |
Each step commits to its own database immediately. The next step is triggered by the success of the previous one — via an event message or a direct call.
The Crucial Trade-off: Intermediate Visibility
Unlike 2PC, there are no global locks held across these steps. This means other parts of the system can observe intermediate states. Between Step 1 and Step 3, an order exists in the database with status PENDING. A customer support agent querying the database would see it. A monitoring dashboard would count it.
This is eventual consistency: the system is temporarily inconsistent during the saga's execution, but will reach a consistent final state once all steps complete (or all compensations execute). For most business processes, this is perfectly acceptable — and it's the trade-off that enables the scalability and availability that 2PC cannot provide.