Microservices and CQRS
CQRS can be implemented with microservices:
- • The communication infrastructure can implement the command queue when a messaging solution is used. With approaches such as REST a microservice has to forward the commands to all interested command handlers and implement the command queue that way.
- • Each command handler can be a separate microservice and can handle the commands with its own logic. This enables logic to be very easily distributed to multiple microservices.
- • A query handler can also be a separate microservice. The changes to the data which the query handler uses can be introduced by a command handler in the same microservice. However, the command handler can also be a separate microservice. In that situation the query handler has to offer a suitable interface for accessing the database so that the command handler can change the data.
CQRS has a number of benefits particularly when it comes to the interplay between microservices:
- • Reading and writing of data can be separated into individual microservices. This makes possible even smaller microservices. When the writing and reading is so complex that a single microservice for both would get too large and too hard to understand, a split might make sense.
- • Also a different model can be used for writing and reading. Microservices can each represent a Bounded Context and therefore use different data models. For instance, in an e-commerce shop a lot of data may be written for an online purchase while statistical evaluations read only a small part of that data for each purchase. From a technical perspective the data can be optimized for reading operations via denormalization or via other means for certain queries.
- • Writing and reading can be scaled differently by starting a different number of query handler microservices and command handler microservices. This supports the fine-grained scalability of microservices.
- • The command queue helps to handle any load peaks that occur during writing. The queue buffers the changes that are then processed later on. However, this does mean that a change to the data will not immediately be taken into consideration by the queries.
- • It is easy to run different versions of the command handlers in parallel. This facilitates the deployment of new versions of the microservices.
CQRS can serve to make microservices even smaller, even when operations and data are very closely connected. Each microservice can independently decide for or against CQRS.
There are different ways to implement an interface that offers operations for changing and reading data. CQRS is only one option. Both aspects can also be implemented without CQRS in just one microservice. The freedom to be able to use different approaches is one of the main benefits of microservice-based architectures.
CQRS also brings some challenges:
- • Transactions that contain both read and write operations are hard to implement. The read and write operations may be implemented in different microservices. This may mean it is very difficult to combine the operations into one transaction since transactions across microservices are usually impossible.
- • It is hard to ensure data consistency across different systems. The processing of events is asynchronous, meaning that different nodes can finish processing at different points in time.
- • The cost for development and infrastructure is higher. More system components and more complex communication technologies are required.
It is not wise to implement CQRS in every microservice. However, the approach can be valuable for microservice-based architectures in many circumstances.