Context
You have applied the Database per Service pattern. Each service has its own database. Some business transactions, however, span multiple service so you need a mechanism to implement transactions that span services. For example, let’s imagine that you are building an e-commerce store where customers have a credit limit. The application must ensure that a new order will not exceed the customer’s credit limit. Since Orders and Customers are in different databases owned by different services the application cannot simply use a local ACID transaction.
Problem
How to implement transactions that span services?
Forces
- 2PC is not an option
Solution
Implement each business transaction that spans multiple services as a saga. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.
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
Example: Choreography-based saga
An e-commerce application that uses this approach would create an order using a choreography-based saga that consists of the following steps:
- The
Order Servicereceives thePOST /ordersrequest and creates anOrderin aPENDINGstate - It then emits an
Order Createdevent - 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 theOrder
Example: Orchestration-based saga
An e-commerce application that uses this approach would create an order using an orchestration-based saga that consists of the following steps:
- The
Order Servicereceives thePOST /ordersrequest and creates theCreate Ordersaga orchestrator - The saga orchestrator creates an
Orderin thePENDINGstate - It then sends a
Reserve Creditcommand to theCustomer Service - The
Customer Serviceattempts to reserve credit - It then sends back a reply message indicating the outcome
- The saga orchestrator either approves or rejects the
Order
Resulting context
This pattern has the following benefits:
- It enables an application to maintain data consistency across multiple services without using distributed transactions
This solution has the following drawbacks:
- The programming model is more complex. For example, a developer must design compensating transactions that explicitly undo changes made earlier in a saga.
There are also the following issues to address:
-
In order to be reliable, a service must atomically update its database and publish a message/event. It cannot use the traditional mechanism of a distributed transaction that spans the database and the message broker. Instead, it must use one of the patterns listed below.
-
A client that initiates the saga, which an asynchronous flow, using a synchronous request (e.g. HTTP
POST /orders) needs to be able to determine its outcome. There are several options, each with different trade-offs:- The service sends back a response once the saga completes, e.g. once it receives an
OrderApprovedorOrderRejectedevent. - The service sends back a response (e.g. containing the
orderID) after initiating the saga and the client periodically polls (e.g.GET /orders/{orderID}) to determine the outcome - The service sends back a response (e.g. containing the
orderID) after initiating the saga, and then sends an event (e.g. websocket, web hook, etc) to the client once the saga completes.
- The service sends back a response once the saga completes, e.g. once it receives an
Related patterns
- The Database per Service pattern creates the need for this pattern
- The following patterns are ways to atomically update state and publish messages/events:
- A choreography-based saga can publish events using Aggregates and Domain Events
- The Command-side replica is an alternative pattern, which can replace saga step that query data


