This post originated from an RSS feed registered with Agile Buzz
by Martin Fowler.
Original Post: Bliki: CQRS
Feed Title: Martin Fowler's Bliki
Feed URL: http://martinfowler.com/feed.atom
Feed Description: A cross between a blog and wiki of my partly-formed ideas on software development
CQRS stands for Command Query Responsibility Segregation. It's a
pattern that I first heard described by Greg Young. At its heart is
a simple notion that you can use a different model to update
information than the model you use to read information. This simple
notion leads to some profound consequences for the design of
information systems.
The mainstream approach people use for interacting with an
information system is to treat it as a CRUD datastore. By this I
mean that we have mental model of some record structure where we can
create new records, read records, update
existing records, and delete records when we're done with
them. In the simplest case, our interactions are all about storing
and retrieving these records.
As our needs become more sophisticated we steadily move away from
that model. We may want to look at the information in a different
way to the record store, perhaps collapsing multiple records
into one, or forming virtual records by combining information for
different places. On the update side we may find validation rules
that only allow certain combinations of data to be stored, or may
even infer data to be stored that's different from that we
provide.
As this occurs we begin to see multiple representations of
information. When users interact with the information they use
various presentations of this information, each of which is a
different representation. Developers typically build their own
conceptual model which they use to manipulate the core elements of
the model. If you're using a Domain Model, then this is usually the
conceptual representation of the domain. You typically also make the
persistent storage as close to the conceptual model as you can.
This structure of multiple layers of representation can get quite
complicated, but when people do this they still resolve it down to a
single conceptual representation which acts as a conceptual
integration point between all the presentations.
The change that CQRS introduces is to split that conceptual model
into separate models for update and display, which it refers to as
Command and Query respectively following the vocabulary of
CommandQuerySeparation. The rationale is that for many
problems, particularly in more complicated domains, having the same
conceptual model for commands and queries leads to a more complex model that
does neither well.
By separate models we most commonly mean different object models,
probably running in different logical processes, perhaps on separate
hardware. A web example would see a user looking at a web page
that's rendered using the query model. If they initiate a change
that change is routed to the separate command model for processing, the
resulting change is communicated to the query model to render the
updated state.
There's room for considerable variation here. The in-memory
models may share the same database, in which case the database acts
as the communication between the two models. However they may also
use separate databases, effectively making the query-side's database
by a real-time ReportingDatabase. In this case there
needs to be some communication mechanism between the two models or
their databases.
The two models might not be separate object models, it could be
that the same objects have different interfaces for their command
side and their query side, rather like views in relational
databases. But usually when I hear of CQRS, they are clearly
separate models.
CQRS naturally fits with some other architectural
patterns.
As we move away from a single representation that we interact
with via CRUD, we can easily move to a task-based UI.
Interacting with the command-model naturally falls into
commands or events, which meshes well with Event Sourcing.
Having separate models raises questions about how hard to keep
those models consistent, which raises the likelihood of using
eventual consistency.
For many domains, much of the logic is needed when you're
updating, so it may make sense to use
EagerReadDerivation to simplify your query-side models.
CQRS is suited to complex domains, the kind that also benefit
from Domain-Driven Design.
When to use it
Like any pattern, CQRS is useful in some places, but not in
others. Many systems do fit a CRUD mental model, and so should be
done in that style. CQRS is a significant mental leap for all
concerned, so shouldn't be tackled unless the benefit is worth the
jump.
In particular CQRS should only be used on specific portions of a
system (a Bounded
Context in DDD lingo) and not the the system as a whole. In this
way of thinking, each Bounded Context needs its own decisions on how
it should be modeled.
So far I see benefits in two directions. Firstly is handling
complexity - a complex domain may be easier to tackle by using
CQRS. I do have to hedge this, usually there's enough overlap
between the command and query sides that sharing a model is
easier. Each domain has different characteristics.
The other main benefit is in handling high performance
applications. CQRS allows you to separate the load from reads and
writes allowing you to scale each independently. If your application
sees a big disparity between reads and writes this is very
handy. Even without that, you can apply different optimization
strategies to the two sides. An example of this is using different
database access techniques for read and update.
If your domain isn't suited to CQRS, but you have demanding
queries that add complexity or performance problems, remember that
you can still use a ReportingDatabase. CQRS uses a
separate model for all queries. With a reporting database you still
use your main system for most queries, but offload the more
demanding ones to the reporting database.
It's also true that we haven't seen enough uses of CQRS in the
field yet to be confident that we understand its pros and cons. So
while CQRS is a pattern I'd certainly want in my toolbox, I wouldn't
keep it at the top.