I think one of the most interesting patterns in software engineering is Command Query Responsibility Segregation (CQRS). It is a super powerful way of thinking about certain problems and a way of building systems that solve these problems.
There’s a wealth of great material around this pattern and how to use it for building software. If you’d like more information then I’ve included a section at the end of this post with a list of useful resources.
In this post, rather than explain all the details of CQRS, I want to just focus on what I think is the essence of this pattern. Armed with this information you can then go off and explore the subject in more detail.
Why CQRS?
Consider a more traditional software architecture: you generally start by creating a domain model of your problem space and the use-cases that it supports. The next step is usually to then work out how to persist and retrieve that model using the database of your choice. Finally you create services and APIs that allow the domain model to be created, updated and queried.
For many domains, this pattern works reasonably well, but what happens if the domain has very different requirements and constraints for updating vs reading?
An example
Back in 2009 I worked for an organisation that wrote news articles and published these to their high volume consumer facing website. The two parts to this process were incredibly different…
The requirement for creating and updating the articles was very much one where a small number of people (usually a reporter and an editor) wrote text, added images and created layouts. Changes were typically carried out in small increments and it was important to keep a full modification history of the article as it was developed (to allow reverting changes, re-working text, auditing etc.). Once completed the article was marked as being ready for publication. After publication some articles would often undergo small corrections or modifications, and then be re-published.
The requirement for reading the articles was the exact opposite. It was one of high numbers of concurrent readers (especially for important breaking news). Speed of rendering the article was the most important concern. The readers were only allowed to view the latest published version and had no access to older versions of the same article.
In this example and with our traditional architecture:
- Do we build our domain model to be flexible and optimised for the creating and updating tasks, possibly making the reading process less efficient or highly resource intensive? OR
- Do we build our domain model for fast reading and rendering, either by limiting the creating and editing functionality or making this much more complex that it otherwise might need to be?
In this example it turned out that neither of these two approaches would have delivered the system that the business really needed. So where do we go from here?
Enter the CQRS pattern
The essence of the CQRS pattern is that rather than having a single domain model that must serve all purposes, we instead separate the domain into different models. Each of these models is designed and structured to meet a specific set of requirements. Typically this ends up being two domain models:
- The model for creating and updating - known as the Command Model
- The model for reading - known as the Query Model
In the CQRS pattern the Command Model is generally the richer domain model and acts as the source of truth for the state of the system. It receives commands in the form of actions to be undertaken on the domain (e.g. UpdateArticleTitle) and makes business decisions about how these change the domain model.
At certain points the Command Model may decide that there has been sufficient change to the domain state that needs to be reflected in the Query Model. When this occurs, the Command Model sends a notification to the Query Model, usually in the form of an Event.
On receiving the notification, the Query Model updates its own simplified model of the domain that is optimised for quickly and efficiently serving queries and rendering views. Often the Query Model is denormalised and may contain data duplication in order to serve queries for multiple different view points.
The Query Model receives queries that trigger a read and return of information from the model (e.g. GetArticleContent). The only updates that occur on the Query Model are those triggered via the notifications from the Command Model. For all intents and purposes, clients of the Query Model see it just as a highly optimised readonly view.
Summary
From the above we can see that CQRS offers an elegant approach to designing and building systems there there are very differing constraints between the domain model state that is being updated and the view of the domain model being read.
Resources
Here’s a list of useful CQRS resources that you can use to continue your journey:
- Martin Fowler’s Overview of CQRS
- Azure CQRS Cloud Design Pattern
- RedHat Guide to CQRS
- Axon CQRS Overview
- AxonIQ - Framework and Server