Once your business logic gets more complex, scalability becomes an issue, and your application’s performance is causing you more and more problems, it’s definitely time to reconsider your architecture.
Therefore, implementing the CQRS pattern can be one of the best solutions.
CQRS stands for Command Query Responsibility Segregation. It’s a design pattern which allows us to represent and manipulate the information differently for reads and writtes, using Commands to update the data, and Queries to read it.
Now, having separate requirements for updating and displaying the information is no longer causing problems to the development team.
Even if the main concept is quite simple: to separate reads from writes; when combining CQRS with Microservices, Event-driven architecture, etc. , things may get very complicated.
Thats why CQRS is a powerfull tool that can add a lot of value to your project, but it can also become a headache if you don’t know how and when to use it properly.
⦁ Separation of concerns
Commands either changes the state of an object, has side-effects or fulfills both criteria at the same time.
Queries read and returns the information about the state of an object from different data stores and they don’t change the state of the system (never modify a database.).
⦁ Maintenance and flexibility
Using different models to update and read domain data, you can end up with very simple Queries and add more complex logic only to the Commands if you need it, managing and optimizing them independently.
Working with only one large database, can cause you a lot of problems when handling the growing number of complex reads and writes, resulting in errors, bottlenecks, etc.
With CQRS you can build your architecture to support 2 separate databases for reading and writing data. Having a relational database for writing and a non-relational database for reading, can also increase a lot the performance of your application.
Of course this method leads to other issues that should be taken into account:
- How the two databases must be synchronized?
- How to guarantee availability and consistency between the read and write sides?
But, if all this effort will resolve your problems and will add value to your project then it definitely worth to spend more time on designing the architecture, instead of loosing more later on refactoring.
⦁ Integration with Event Sourcing and Microservices
With the widespread adoption of Microservices, there are also a lot of advantages of implementing Event-driven techniques in distributed systems.
By using them, you can easily create loosely coupled components, ensure modularity with separate databases, handle atomic operations; which with no doubt will lead to highly scalable and fault tolerant systems.
Therefore, it makes it easier to add new modules/components to a system without needing to modify the existing ones, to continuously deliver features as a part of a larger ecosystem of other microservices and to deliver high quality code quickly.
We can’t really avoid the complexity growth of the overall system design over time, that’s why apart from a good dev team you also need a good technical project management that can take advantage of the benefits that CQRS (especially integrated with Microservices and Event Sourcing) can offer.
When to use it?
If you have a small project and a simple business logic, it will be difficult to estimate whether it is worth the effort or not, because it will be too overwhelming to implement it. In this case, more probably, you don’t need to use this pattern.
But if you have a large-scale distributed system, with modern asynchronous user interfaces, where availability and scalability are very important, you definitely need to consider implementing CQRS.