In this post we will be looking at the Command-Query Responsibility Segregation (CQRS) and Event Sourcing (ES) patterns. I’ve spent a some time getting my head wrapped around these two ideas. These patterns are complex enough that the time spent learning them was necessary to truly understand what was going on. Hopefully this post will save some time for other people. While CQRS and ES are useful, they’re pretty involved and difficult to understand if you’re seeing them for the first time. They provide some huge benefits once you get past the initial complexity. So this post is to help get past that initial complexity.
Command-Query Responsibility Segregation(CQRS)
The vast majority of modern application functionality can be summed up to the acronym CRUD:
- Create
- Read
- Update
- Delete
We create objects, read them, modify them. Mostly all functionality in any given app (that isn’t trivial) can fall into one of these general categories. This leads to an application model that is relatively simple to understand; which may look like this:
In other words, we have an Application that contains a Model of our data, and uses that Model to query a Database for the data itself. For most applications, this is pretty good way of architecting a solution.
While this model works for a great deal of applications, as our application evolve, the CRUD model starts to fall short. More intricate applications require a more complex application model, and one possible solution is to use Command-Query Responsibility Segregation (CQRS).
The essence of CQRS is that you use a different model to read the data than you do to modify it. An updated application model would look like this:
What this allows, among other things, is for the developers to optimize each side (commands and queries) separately for their respective operations. Further, modifications to the models only affect their corresponding applications.
Taken to an extreme, CQRS can enable you to have entire different interfaces, datastores, even complete tech stacks for the query and command sides of you application. Of course, nothing about CQRS says you have to do any of that; the only thing you need to do to satisfy CQRS is to use different models for commands and queries.
Event Sourcing
The second, and distinct, architectural pattern we’ll be using is Event Sourcing (ES). In short, Event Sourcing is a different way of thinking about data storage. Much of the time, we use datastores that reflect the model of our data.
A great number of databases will use similar models; one table per entity, with relationships and keys and such. In other words, CRUD data models store the data in its current state.
Event Sourcing asks you, to forget the CRUD model and instead store the changes made to the data using an append-only database store, known as an Event Store. In this architecture, we store all changes made to the data as serialized events, which can be re-run at later time to get us the current state of any object. This pattern allows us to get the state of a given object at any point in the past, which is a great help when debugging certain problems. Further, because all events are serialized, we only need one database table to represent our entire event store.
One point to make here is that Event Sourcing doesn’t store the current state of the data. Instead, when a particular object is modified, Event Sourcing re-executes all events on that particular object before making the new change. This means that we could have thousands of events executed every time a change is made (though this can be negated via the use of snapshots, which are “pictures” of the data made at a specific point in time, and are then used as starting points for subsequent events).
Using CQRS and ES Together
While these two patterns (CQRS and ES) are orthogonal, they fit together quite nicely. The Event Store from ES becomes CQRS’s Write Model, and the design of the Read Model is irrelevant to how ES behaves. A sample model of how the two patterns fit together can be seen in this diagram:
Let’s be frank: CQRS/ES is a lot of work to set up, and the benefits of doing so are not always clear. In fact, one of the proponents of this architecture, Martin Fowler, actually recommends not using CQRS unless you have a clear reason to do so. The pattern is most useful in applications that need to scale both horizontally and vertically and don’t mind having to deal with a lot of architectural overhead.
For a more in-depth explanation of these ideas, check out Martin Fowler’s blog entries for CQRS and Event Sourcing, or read A CQRS Journey from Microsoft Development.