Really Simple CQRS

Whenever I teach my IDDD Workshop and reach the first section that discusses CQRS (Command-Query Responsibility Segregation) I ask if anyone is already familiar with it. I have been doing this for more than six years of teaching this curriculum, and as you can probably imagine there are now far more students who raise their hand to indicate familiarity with CQRS than there were six years ago. Nonetheless, when I begin to cover just the basics of CQRS in the classroom, the visual feedback and questions that I get shows that “familiarity” translates to “aware of.”

Perhaps the students have heard colleagues discuss it briefly. They may have read tweets or a blog post or attended a conference talk where CQRS was mentioned or even treated with some greater degree of detail. Still, it’s unusual to find many who understand what it really means.

Why CQRS?

Software developers commonly face a design challenge because users tend to view data in quantities, shapes, and sizes that is different from the way they modify data. Using a traditional domain model that provides both mutation and query operations on a single software model results in the following problems, because the data users view cannot be retrieved as optimally as is generally possible for mutation.

Given that the system state that the user wants to view is rich and cuts across at least several logical system concepts, and that the state that the user wants to mutate tends to be concentrated, the strengths of CQRS are in enabling developers to design for state mutation separately from state queries. The state mutation operations are optimized for creates and updates. The operations and data used for querying are optimized for how the user tends view the system state. Both of these sets of operations and states can be designed and scaled separately. In brief, the above software design challenge can be addressed and related problems overcome with the use of CQRS.

CQRS and Architecture

One of the primary misunderstandings even among those who claim to know CQRS well, and who attempt to teach it, is thinking that CQRS is a system-level architecture or a top-level architecture, as in an architectural style. It’s possible that some think this simply because they don’t understand what constitutes a top-level architecture, or architectural style. An architectural style describes the pattern that is followed by an entire application or service (possibly even a microservice), and not just some small portion of the the overall application or service. For example, there are Layers architecture and Ports and Adapters architecture.

Ports and Adapters is an architecture that has an impact on the way an application or service as a whole works. When the Ports and Adapters architecture is used, everything within the application or service reflects some well-defined part of definition of Ports and Adapters. Although Ports and Adapters highlights the outside with input and output ports and the software adapters that support them, the architecture also defines the inside with the application interfaces. Additionally, the application inside may be further divided into application services and a domain model. You will probably recognize this diagram from my book Domain-Driven Design Distilled. The same architecture is discussed with more detail in my book Implementing Domain-Driven Design.

Considering the previous description of an architectural style, CQRS is not intended to be that, meaning it doesn’t necessarily have an impact on the overall application or service. Instead, CQRS is an architecture pattern; one that has some substantial influence on the inner workings of the application or service, but not every part of it. With that in mind, consider what CQRS actually means.

Meaning

The CQRS architecture pattern is based on the CQS software principle defined by Bertrand Meyer, creator of the Eiffel programming language. To understand CQRS it helps to first understand CQS. It’s fitting then that I provide a few definitions.

CQS, or Command-Query Separation states that a software interface abstraction is designed with two types of methods. One method type is known as a Command method, and the other method type is known as a Query method. A Command method modifies or mutates the state underneath the interface, but does not answer any portion of that state. A Query method answers the current state beneath the interface, but must not modify that state before answering it. In particular note that CQS mandates the definition of the methods of a single interface abstraction. In the literature CQS is not considered a pattern, but a principle. I don’t want to split hairs over this, because you might argue that CQS is a design pattern, but it’s difficult to find official definitions to support that argument.


public interface Thing {
  void rename(String name);
  ...
  String name();
  ...
}

In this example interface, the Thing has a state that holds its name and can be queried using the name() method. After rename() is used the name() method will answer the value of the String passed as an argument to rename().

CQRS, or Command-Query Responsibility Segregation is similar to CQS because it focuses on separating Command methods and Query methods, but it does so to an even greater degree. This is a good time to highlight the terms responsibility and segregation. The term responsibility conveys the idea that Commands are not only a type of method, but a type of software responsibility. The same goes for Queries. The term segregation emphasizes that the two responsibilities, Commands and Queries, are segregated from each other using separate interfaces. Thus, where there is one Thing interface in the above example, there are now two interfaces.


public interface ThingCommands {
  void rename(String name);
  ...
}

public interface ThingQueries {
  String name();
  ...
}

It seems important to note that the above segregated interfaces emphasize why CQRS is not an architectural style, but an architecture pattern. Since Thing is likely not the only business concept in the application or service, there could be several other business model concepts defined, such as Thing1 and Thing2. These are concepts that are more closely associated with the interior of the application or service, generally know as the domain model. But, there’s more to this story.

I don’t think that it is oversimplifying things to say that CQRS is just that simple.

Command Model and Query Model

Considering a traditional domain model, there is just one model that defines the application’s or service’s state. Defining our business concepts using the CQS principle, there is still just one root object constituting a Thing.

When using CQRS it is typical to use not one, but two, models, those being a Command Model and a Query Model. This is part of the segregation, but in addition to the interfaces there are the software models of the segregated states. There are a segregated states used by the Commands, and segregated states used by the Queries. This is at least a logically segregation because there is nothing to prevent the implementation from managing Command states and Query states together, but it is easier to reason about two state models rather than one.

When methods on the ThingCommands interface are executed, the Command Model state is mutated. When methods on the ThingQueries interface are executed, the Query Model state is queried. That makes sense, except for how the Query Model state comes about. This is illustrated by the following diagram.

The Query Model is built up by projecting the changes made to the Command Model on to it. In other words, as the user submits Command operations, the outcome of the Command Model mutations are used by software components to projection appropriate updates onto the Query Model. The user views the system state by way of the use-case-optimized Query Model.

In the above diagram, the Command Model mutations are captured by Domain Events, which are also used to project updates onto the Query Model. It is not necessary to use Domain Events for this. The entire state of a Command Model object that is mutated may be projected instead. If this approach is used, it’s helpful to indicate to the projection components what the actual Command operation was that caused the state to mutate. This enables the projection components to have both a rich set of data to project, but with full knowledge of the actual state that changed. You can see this technique used in the XOOM Platform example found here.

Tools for CQRS

Although I wanted to keep this initial post mostly free of tooling technology, I will be sharing some more information in later posts on how you can use DDD-friendly XOOM Platform for building microservices using fluent APIs that fit well with fluent domain models.

More to explore

Reactive DDD: Modeling Uncertainty

Domain-Driven Design supports reactive architecture and programming. Still, reactive introduces uncertainty. Back in 2003, the way that Domain-Driven Design was used and

Scroll to Top