CQRS (command query responsibility segregation)

Command query responsibility segregation (CQRS) is a programming design pattern that treats retrieving data and changing data differently. CQRS uses command handlers to simplify the query process and hide complex, multi-system changes.

The design pattern was developed by Bertrand Meyer as a way to ensure that a method working with data is only allowed to perform one of two tasks. A method can either retrieve information or it can modify it, but it can't do both. In object-oriented terms, this paradigm separates responsibilities into two different classes -- one for read and the other for delete, create and update.

When CQRS is combined with event sourcing, it guarantees an audit log of changes to the database that maintains transactional consistency.

How the CQRS pattern is implemented

The most common way to implement CQRS is the command pattern, which is the software system that defines a high-level interface. At runtime, the base class takes the command, creates the appropriate object handler (perhaps update, delete or create) and calls a method to execute the command.

Before and after the execution, the base class can log that the method was called. This creates a log that can be replayed from and to any point in time. Once the interface and dispatch code exist, the computer program to take the events and replay them is not much more complex than a for loop. That is, the program reads a file from a certain point, and then for each line, calls the command on that line with the data on that line. There is a great deal of complexity hidden inside the command handler, but it is limited, or encapsulated by the handler.

The handlers themselves call each step of the process to create, update or delete a logical item in the system. It can dispatch the first request, but also monitor to see when that action completes, handling errors and rollbacks if needed. That means the handler implements a long-running two-phase commit, sometimes called a saga pattern. When the handler completes (or the transaction fails and errors), the handler will write the results to the event log.

A system that creates and tracks changes in this way will eventually create an event log with a record of every system change. If this log is created in a consistent way that a program can read and replay, it enables event sourcing.

CQRS pattern
A diagram of how a CQRS pattern works.

CQRS example

An example of CQRS can be seen during a customer's order process. When the customer looks at an order, the process is relatively straightforward: a read from a database. In practice, that read could be from a NoSQL key-value store, such as Redis. This key-value stores all the easy-to-access information about the customer in one place. A microservice picks up the information and a webpage displays it. The read side is simple and can be done entirely by the Redis team working with the front-end developers. Thus, the responsibility for the read of CQRS is separated from the write.

The write side of the operation, however, is much more complex and contains several different steps and dependencies. For example, if an order is cancelled before it is shipped, the return needs to be cancelled in the cache and it needs to be returned in the main source system of record. Companies with a data warehouse will need to delete the record from the warehouse, as well as other auxiliary systems. The physical warehouse and shipping need to be notified to not ship the item. Other complexities can include the credit card charges needing to be reversed, inventory counts in the warehouse needing to be changed and the refill order from the supplier needing to go down by one.

Because a single change needs to be copied to so many places, the update, delete and create side of the operation will need to interact with either an enterprise service bus (ESB) or a command-handler, such as the saga pattern. CQRS provides a place to put the logic to handle these complex transactions.

Challenges of CQRS

The main challenge of CQRS is also, in a way, its benefit. The approaches create a layer of complexity on top of the existing codebase. Instead of a simple SQL, now the application will have command handlers, dispatching and logging. All this additional code creates the potential for error.

Because CQRS solves a complexity problem, it appeals to organizations that already have an existing system that is becoming more complex. That existing system might not have such a complex log of transitions, or may use overnight batch mode to do updates. Conversion of such a currently online, running system to CQRS may be a challenge.

CQRS and event sourcing

Sourcing suggests that the system itself can be re-created as the collection of all the changes over time. That creates a new view of data within a software system, the transaction log. With event sourcing, the log is more than a text file, but an actual set of commands that can be replayed to re-create the change. In some cases, the event log can be "played backward" to undo large changes. Implementing event sourcing requires capturing the changes, along with building the software to replay those changes. Implemented carefully, the command handlers can write to a log creating the transaction log for event sourcing. Running each line in the log through a command handler actually implements event sourcing. The two patterns have considerable overlap. The "command" in CQRS is essentially one way to create event sourcing.

What are some related patterns?

CQRS aligns the work of developers to what happens in the organization when, for example, an order is created. This is compatible with the approaches of domain-driven design, an explicit domain model, event sourcing and the command pattern. The messages to perform the create, update and delete may be delivered by an enterprise service bus, while the general pattern for architecture is service-oriented architecture (SOA).

This was last updated in February 2021

Continue Reading About CQRS (command query responsibility segregation)

Dig Deeper on Event-driven architecture (EDA)