63
votes

My team and I have been discussing using the CQRS (Command Query Responsibility Segregation) design pattern and we are still trying to asses the pros and cons of using it. According to: http://martinfowler.com/bliki/CQRS.html

we haven't seen enough uses of CQRS in the field yet to be confident that we understand its pros and cons

So what do you guys think, when does a problem call for using CQRS?

9
Darren Cauthon does a nice presentation on CQRS and Event Sourcing, including the drawbacks - Google says it's available here, but I can't verify that through our firewall. - TrueWill
he personally hasn't seen it in the field - Henrik

9 Answers

62
votes

CQRS is not a pattern that encompasses the whole application.

It is a concept that builds on Domain Driven Design (DDD). And an important strategic concept of DDD is the so-called Bounded Context.

In a typical application there are multiple bounded contexts, any of which can be implemented the way it makes sense. For instance

  • User Management -> CRUD
  • Invoicing -> CRUD
  • Insurance Policy Management (the Core Domain) -> CQRS
  • ...

This probably doesn't answer your question but it might give a little more insight into the topic. To be honest, I don't think it can be answered at all without considering a project's specifics, and even then there is rarely something like a definite best practice.

34
votes

Well CQRL critics may say that CQRS is complicated and that might be true.

Of course, it's adding overhead developing a simple CRUD application in the CQRS style, so I'd consider using CQRS only in the following cases:

  1. Large team - You can split development tasks between people easily if you have chosen CQRS architecture. Your top people can work on domain logic leaving usual stuff to less skilled developers.
  2. Difficult business logic - CQRS forces you to avoid mixing domain logic and infrastructural operations.
  3. Scalability matters - With CQRS you can achieve great read and write performance, command handling can be scaled out on multiple nodes and as queries are read-only operations they can be optimized to do fast read operations.
13
votes

When you have a complex or hard business domain and:

  • with event sourcing; you want a nice way of testing logic
  • with event sourcing; you want to prove your behaviours through testing and reasoning
  • you have multiple clients, or consumers, of your domain service (not just single web server)

OR you have users that need to act on common data:

  • and you want to formalize the data merge concepts of your domain
  • or you want to apply logic for merging events

OR you have scalability requirements:

  • you apply the pattern as a denormalization pattern that removes bottlenecks
  • you want to scale horizontally and not vertically

OR you have performance problems (other side of scalability):

  • e.g. you need to migrate your architecture towards an event driven architecture - CQRS as a pattern is a good stepping stone.

OR you have a team that is physically disjunct:

  • e.g. parts of your team is in another country
  • or it's hard to get face-to-face communication, so you want to decouple the read models from the write-side of things (sagas, domain, CRUD)

It's not CQRS that's overly complicated, it's computers that are.

11
votes

When to use the CQRS design pattern?

The CQRS architecture pattern could be used when it is difficult to query from repositories all the data that users need to view. This is especially true when UX design creates views of data that cuts across several aggregate types and instances. The more sophisticated your domain, the more this tends to be true.

When it is unsuitable to compromise on UX design, using CQRS attempts to mitigate the problems associated with other solutions, such as:

  • requiring clients to use multiple repositories to retrieve all aggregate instances; or
  • the design of specialized finders on various repositories to gather disjointed data using a single query.

To summarize: Use CQRS when its difficult to query from repositories data users need to view, which tend to happen the more sophisticated your domain is.

3
votes

In real world scenario CQRS might be useful when you have front end/web service client which needs lots of data from multiple domains and retrieval of these data from database takes long time.

In such case you might consider creation of separate read model which will be faster to develop and might have faster execution time.

2
votes

Following are the reasons to use CQRS:

  1. Scalability (read exceeds the write, so does the scaling requirements for each differs and can be addressed better)
  2. Flexibility (separate read / write models)
  3. Reduced Complexity (shifting complexity into separate concerns)
  4. Concentrate on Domain / Business
  5. Facilitates designing intuitive task-based UIs
0
votes

If you are seeing that the problem domain doesn’t fit well into more generic architecture or you are experimenting with domain-driven design, I’d recommend you to give CQRS a shot.

It is a powerful pattern, which might give you good exposure to the problem domain as well as solve some technical and infrastructural challenges. But it is worth keeping in mind that it will come with its price and due to conceptual differences with other architectures, it will require a mental-model shift.

CQRS: Intro

0
votes

Use it when :

  1. Have a complex domain and need to understand domain by commands
  2. Application load with read and write differes
  3. Want to scale read operations at any point of time

https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs#when-to-use-this-pattern

-1
votes

With regards to implementing CQRS, I like the idea of separating read models when you have a front end/web service client requiring lots of data from multiple domains, and I would like to try it. My primary reason for wanting to try it is due to the issue with 'slowness'in development and execution processes; especially when it comes to handling large data sets, or 'big data'. I'm looking at all the various options available in reducing complexity(ies), adding scalability, resiliency, and flexibility to a hybrid architecture.