A Critical Look at CQRS

| by Jan Stenberg Follow 38 Followers on Jul 20, 2015. Estimated reading time: 3 minutes |

Looking at Command Query Responsibility Segregation (CQRS) in a larger architectural context there are other architectural styles available, e.g. Event-Driven Architecture (EDA) and Publish-Subscribe. There are also traditional database technologies available that may solve the same problems but in a much simpler way, Udi Dahan states looking into different ways of approaching CQRS. When CQRS is really needed he claims there is an alternative way of implementing that fulfils a lot of the CQRS goals but with fewer moving parts compared to traditional CQRS.

Scalability is one reason for a CQRS approach that Dahan, one of the forefront figures of CQRS together with Greg Young, repeatedly finds when talking to customers. With a large amount of reads, separating reads from writes enables scaling of the queries, but Dahan notes there is already technology available that does read/write separation with little or no code written which he thinks developers should be aware of. One other reason Dahan thinks exists is a social pressure of adopting CQRS since so many talks about it worldwide.

One alternative for achieving scalability in a read intensive environment is master/slave replication with one master where data is modified and one or more read slaves to which all changes are replicated. This is an old, fully supported database mechanism that Dahan defines as a kind of CQRS since it separates writes from reads. He notes that when doing complex joins to build query results there may be latency problems which this replication will not solve, but it can still solve a throughput problem by adding more slaves.

Another solution Dahan suggests solving a scalability problem is sharding or database partitioning, dividing data in one table across multiple instances of a database using e.g. customer name to distribute over the instances. One advantage this gives is multiple masters, enabling scaling of both the command and the query side. Partitioning is available out of the box from many database technologies and can be implemented with fairly simple code. He notes that multiple masters will not work with cross-record transaction, thus requiring the same partitioning of the business domain as in the solution domain.

One situation where Dahan believes there is a case for a CQRS approach is in high contention domains with a very high and extremely localized load, e.g. a large number of requests competing for one or a few records in a database. One failure scenario is that most transactions start to fail due to concurrency exceptions, locking up database connections and client requests, creating a huge bottleneck. Often this is an overlooked test case during performance tests, when testing scalability commonly the load is created using many requests working on many records instead of all requests targeting only a few records. Even with a perfect implementation of CQRS the bottleneck will show up on the query side, the background process cannot update fast enough, causing the query model to fall farther and farther behind.

Dahan’s solution for this contention problem is to move to a model that is event based using a non-blocking append-only data model which means it’s not affected by contention. This can however introduce a problem since it may prevent some business rules, e.g. an order can only be processed if there is enough inventory of products ordered. This solution therefore needs a more flexible business process and a possible change in the requirements. Using the example with orders, the business process should allow for orders to be accepted without inventory checked. If some products are missing in inventory later on when the order is processed the business has to decide how to handle that situation.

Rate this Article

Adoption Stage

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Changing requirements to fit the technology constraint? by Dmytro Lapshyn

While I agree with most of what has been said in the article, there's one thing that looks like a serious concern. At the very end, the article reads:

This solution therefore needs a more flexible business process and a possible change in the requirements

and then

the business process should allow for orders to be accepted without inventory checked. If some products are missing in inventory later on when the order is processed the business has to decide how to handle that situation

Frankly speaking, I can hardly imagine a software architect approaching the management and asking the management to change the way business works because it would make developing software easier. Well, sometimes that could work, but way more often the architect will be told to go and design the software to serve the existing business process because one works the way it works for a good reason.

"solve the same problems"? by Incze Lajos

i simply can't understand the point. cqrs is about the assumption that "commands" and "queries" deserve entirely different, cleanly separable responsibilities (knowledge, authorization, resources, etc.) in an application. this has nothing to do with much lower level technical issues (that e.g. can be solved by sharding), or with more generic communication platforms, such as pub/sub.

if somebody has problems with it's legacy application that can be solved with sharding, that's ok, and it can even be a quicker solution (at the moment). you have your big traditional application, *of course* you'll have problems that need sharding, of course, right now it is cheaper to invest in some measurements and implement a sharding solution (if that kind of problem was pinpointed), than rephrase the application (or part of it) in another, very different architectural style. (tough, you have a good chance, that this kind of problem in an cqrs/microservice environment would not occur, at all.)

the correct title would be (instead of "a critical look at cqrs"): are there any cheaper than cqrs temporary fixes for my legacy problems? -- where cqrs coud be replaced with any different-than-just-used architectural style.

Re: Changing requirements to fit the technology constraint? by Karel van der Walt


how no business is turned away by degrading through 40 levels of service - lowest accepting order without even checking CC...

Re: "solve the same problems"? by David Dawson

It's worth noting that Udi was party to the creation of CQRS, and so well understands all of this, and did so years and years ago.

He appears, from recent talks, to be performing something of a retrospective on the last 10 years of messaging and event theory. I've noted a few of his talks have taken something that he's been at the forefront of and is trying out pushing a radically different approach, to see if potentially it fits better. I haven't asked him if this is intentional, but it is fun to watch.

While I happily disagree with Udi on certain subjects, including this one and his recent "use source control to track features" talk (last DDD exchange). The very fact that he is doing this to something he has so much invested in shows a flexibility of mind that I respect a lot and is something that can be learned from.

Who knows, he may well be right here too. Selling a CQRS has taken a long, long time to get it even semi-mainstream.

Re: "solve the same problems"? by Lajos Incze

i really do respect his achievements and in fact, many things i think to understand about cqrs comes from reading his articles and blogs. no problem here.

Re: "solve the same problems"? by Paweł Kaczor

@Lajos Incze: exactly, +1.

Sharding does not replace CQRS by Alexey Zimarev

With all respect to Udi, what he describes would cover just a small part of what we are trying to achieve when starting a CQRS journey. Indeed, this was more or less the same idea as, for example, Jimmy Bogard is saying for a couple of years now. Splitting one object into two but still having one data storage. Solve scalability problem by optimizing reads on the database level.

What I want from CQRS is an ability to plug in different types of data stores and this is what Udi's suggestion does not cover. Ideally, I want event sources write side so I can recover what happened in the past to a new/restored read side. No sharding is ever able to solve this. But everyone who worked with any relatively complex data-driven application with loads of data in a database, would know that one of the main issues is that the database just contains a system state in a given moment of time. And this state can realitively easy become invalid without any way to reproduce how this has happened and without any reasonable way to fix it. Proper CQRS+ES design would solve this issue with ease. People keep claiming that "classic" CQRS is hard to implement but I don't really believe in this. ES is more complex but if you have your core in place, all the rest just flows naturally. Surely, for a proper ES you need a reliable event store with native projections support and currently this is a biggest problem since we only have one product (Greg's ES) and they have projections in beta for a couple of years by now with constant promises to release soon.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

7 Discuss