Why not two-phase commit: 2PC locks resources across services and couples their availability, so microservices usually use sagas with eventual consistency.
Saga: a sequence of local transactions, each in one service, where every step has a compensating action that undoes it if a later step fails.
Example, place order:
- 1. Order service creates the order as PENDING.
- 2. Payment service charges the customer.
- 3. Inventory service reserves stock.
- 4. Order becomes CONFIRMED.
- If inventory fails: refund the payment (compensation) and mark the order CANCELLED.
Two styles:
- Choreography: services react to each other's events. Simple for a few steps, but the flow is hard to see and debug.
- Orchestration: a coordinator (or a workflow engine such as Temporal or Camunda) tells each service what to do and tracks state. Clearer for complex flows.
Making it reliable:
- Outbox pattern: write the state change and the event in the same local database transaction, then publish from the outbox table, so events are never lost.
- Idempotent handlers, because messages may be delivered more than once.
- Timeouts and a dead-letter queue for stuck sagas.
- Expose intermediate states (PENDING) honestly in the API and UI.