Pattern: Event-driven architecture
patternContext
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 ensure data consistency across services. For example, lets 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 the application cannot simply use a local ACID transaction.
Problem
How to maintain data consistency across services?
Forces
- 2PC is not an option
Solution
Use an event-driven, eventually consistent approach. Each service publishes an event whenever it update its data. Other service subscribe to events. When an event is received, a service updates its data.
Example
An e-commerce application that uses this approach would work as follows:
- The
Order Service
creates an Order in a pending state and publishes anOrderCreated
event. - The
Customer Service
receives the event and attempts to reserve credit for that Order. It then publishes either aCredit Reserved
event or aCreditLimitExceeded
event. - The
Order Service
receives the event from theCustomer Service
and changes the state of the order to either approved or cancelled
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
There are also the following issues to address:
- In order to be reliable, an application must atomically update its database and publish an event. It cannot use the traditional mechanism of a distributed transaction that spans the database and the message broker. Instead, it must use one the patterns listed below.
Related patterns
- The Database per Service pattern creates the need for this pattern
- The following patterns are ways to atomically update state and publish events:
See also
The article Event-Driven Data Management for Microservices by @crichardson describes this pattern