The Command and Query Responsibility Segregation (CQRS) Pattern

The Command and Query Responsibility Segregation (CQRS) it’s an architectural pattern where the main focus is to separate the way of reading and writing data. This pattern uses two separate models:

  • Queries — Which are responsible for reading data
  • Commands — Which are responsible for update data

The Command and Query Responsibility Segregation (CQRS) pattern separates read and update operations for a data store. Implementing CQRS in your application can maximize its performance, scalability, and security.

The image below illustrates a basic implementation of the CQRS Pattern:

Commands

Commands represent the intention of changing the state of an entity. They execute operations like Insert, Update, Delete. Commands objects alter state and do not return data.

Commands represent a business operation and are always in the imperative tense, because they are always telling the application server to do something. A command is an object with a name of an operation and the data required to perform the operation. For example:

The commands are interpreted by the CommandHandlers and they return an event, which can be a successful event or a failure event. If the command succeed it will create a success event, and if the command fails it will create a failure event.

Queries

Queries are used to get data from the database. Queries objects only return data and do not make any changes.

Queries will only contain the methods for getting data. They are used to read the data in the database to return the DTOs to the client, which will be displayed in the user interface.

Queries usually start with the word Get, because queries ask for the application to provide some data, for example:

Separated Databases

When working with CQRS, it’s also possible — but it’s not mandatory — to have separate databases: a database only for reading the data, and a database only for making changes.

In traditional architectures, the same data model is used to query and update a database, and this is great for basic CRUD operations (remember of the KISS principle — if you want to read more about it, click here), but when we deal with more complex applications like microservices or any kind of application that has a high demand for data consumption, the common approach can become unwieldy, because having much writing and reading in the same database can affect the performance of the application (read and write workloads have very different performance and scale requirements). In this scenario you can use a database only for reading — and you can replicate this database to have more performance — and a database just for writing, where everything that will be writing in this database will be replied to the reading database.

The queries are used to execute the reading operations in the reading database and the commands are used to execute the change operations in the database that is used for update. In this case, it’s necessary to keep those databases in sync, one way of doing this is thought the use of events. Always when the command is called and change something in the writing database, a process needs to be called to updated the modified data in the reading database.

It’s also possible to work with messaging together with CQRS, in this case the commands will go to a queue and the domain can read and handle with those commands.

The image below illustrates the CQRS Patter using a database for reading and a database for update:

When the CQRS can be used?

CQRS can be considered to be used on scenarios where:

  • Has a high demand for data consumption
  • Performance of data reads must be tuned separately from the performance of data writes, especially when the number of reads is much greater than the number of writes.
  • There is the need for one team focus on the complex domain model that is part of the write model, while another team can focus on the read model and the user interfaces
  • The system is expected to evolve over time and might contain multiple versions of the model, or where business rules change regularly.
  • Integration with other systems, especially in combination with event sourcing, where the temporal failure of one subsystem shouldn’t affect the availability of the others.

When the CQRS should not be used?

CQRS is not recommended on scenarios where:

  • The domain or the business rules are simple (remember of the KISS principle).
  • A simple CRUD-style user interface and data access operations are sufficient.

Benefits of CQRS

Like we saw before, CQRS can be very handy for some scenarios, and those are some benefits of CQRS:

  • With the separation of concerns, helps to minimize and manage the complexity, making the application more maintainable, extensible, and flexible.
  • Segregating the responsibility between commands and queries can help to improve performance, scalability, and security.
  • The workloads between read and write operation will be different and using CQRS allows you to scale each of them independently of the others.
  • Security is improved because you will have a single object model to execute an update operation ensuring that only the right classes will do it.
  • Because each class is responsible for reads or writes, this reduces the chance of exposing data that should not available to a particular user.

Disadvantages of CQRS

Implementing CQRS also have some disadvantages that must be taken into account:

  • Increase the complexity of the code.
  • If using messaging to process commands and publish update events, the application must handle message failures or duplicate messages.
  • If you separate the read and write databases, the read database may be stale, and it can be difficult to detect when a user has issued a request based on stale read data. Even if you use event-sourcing or some other mechanism to keep the databases sync, there will be some time delay (even if it’s a small one) before the writing database be consistent. So you should consider that maybe you can be reading data that is stale.

Event Sourcing

The CQRS pattern is often used together with the Event Sourcing Pattern (they work very well together). This pattern will be explained with more details in another article, but just to give a brief introduction, with this pattern the application state is stored as a sequence of events, and each event represents a set of changes to the data. This pattern allows us to keep all the states of an entity since it’s creation. With Event Sourcing, we can have not only the history of all changes but also the sequence in which those changes were made in an entity.

Event Sourcing ensures that all changes to application state are stored as a sequence of events. Not just can we query these events, we can also use the event log to reconstruct past states, and as a foundation to automatically adjust the state to cope with retroactive changes. — Martin Fowler

For example, let’s suppose that you have a Product entity with a property “Name”, and on this property, you have the value “Table”. If you change the value for the property name from “Table” to “Chair”, when you get the data from this entity you will just have the new information. But when we work with Event Source, it’s possible to see the older values, because then we have a history of all changes that were made in the entity.

The CQRS pattern does not demand that Event Sourcing must be implemented, nether the Event Sourcing demand that the CQRS must be implemented, you can work with those patterns together or separately.

Although the CQRS can be used without events, they do complement each other so its common for systems that use CQRS to leverage the use of events. Events are one way to effectively communicate state changes so that the query model can stay up to date as the command model updates data.

Conclusion

The CQRS pattern can be very handy for more complex applications or application where we have a high demand for data consumption. For more commons scenarios where just basic operations will be executed, the CQRS can create unnecessary complexity to the application. So before deciding if you will implement CQRS or not, you always should consider what your application demands.

References

Command and Query Responsibility Segregation (CQRS) pattern

Software Architect’s Handbook — Joseph Ingeno

CQRS Documents by Greg Young

Event Sourcing — Martin Fowler

Code with Shadman — CQRS

.NET Full-Stack Developer | C# | .NET | .NET CORE | ASP.NET MVC | Unit Test | Angular

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store