A Saga maintains data consistency across multiple services by using a sequence of local transactions, so without using (ACID) distributed transactions. As an example, think of an e-commerce store where customers can only create orders when their credit limit is not exceeded.
Each local transaction updates the database and publishes a command message or event to trigger the next local transaction in the saga. If a local transaction fails then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions. Compensation is done via coding. This makes the solution more complex. No automatic roll-back is possible, since the related entities are in different databases owned by different services.
There are two ways of coordination sagas:
- Choreography – each local transaction publishes domain events that trigger local transactions in other services
- Orchestration – an orchestrator (object) tells the participants what local transactions to execute
- The Order Service receives the POST /orders request and creates an Order in a PENDING state
- It then emits an Order Created event
- The Customer Service’s event handler attempts to reserve credit
- It then emits an event indicating the outcome
- The OrderService’s event handler either approves or rejects the Order
- The Order Service receives the POST /orders request and creates the Create Order saga orchestrator
- The saga orchestrator creates an Order in the PENDING state
- It then sends a Reserve Credit command to the Customer Service
- The Customer Service attempts to reserve credit
- It then sends back a reply message indicating the outcome
- The saga orchestrator either approves or rejects the Order