Busting some CQRS myths

CQRS, while a relatively simple concept, still brings a lot of assumptions about what CQRS is and should be. So what is CQRS? Simply put, CQRS is two objects where there was once one. We’re splitting code infrastructure down to the data layers between commands and queries.

But the assumptions around what a CQRS should be lead folks I’ve seen down paths of unnecessary complexity. Complexity around the architecture, and especially around the UI.

Myth #1 – CQRS = Event Sourcing and vice versa

Event sourcing often fits well with CQRS, as it makes building and updating read stores over time a bit more straightforward in eventually consistent models. Additionally, the aggregates living in the command side for behavior-heavier systems and task-based UIs more obvious.

However, event sourcing is a completely orthogonal concept to CQRS. While they fit well together, doing CQRS does not require event sourcing, and doing event sourcing does not automatically mean we’re doing CQRS.

For me, the bar for event sourcing is rather high and targeted (only inside a bounded context, for one), but that’s a story for another day.

Myth #2 – CQRS requires an eventual consistent read store

No, it does not. You can make your read store immediately consistent. That is, your read store can be updated when your command side succeeds (in the same transaction).

For many legacy/existing apps, transitioning to eventually consistent read stores will either force you to go through bogus hoops of mimicking synchronous calls. Users will bang down on your door with pitchforks and torches if you try and transition to an asynchronous model if you don’t change their business process first.

Instead, you can start with immediate consistency and transition where and when it’s needed. Unless a user expects a confirmation page, making every command page have a series of confirmations of “your request was received” is going to annoy the snot out of your users.

Myth #3 – CQRS requires a bus/queues/asynchronous messaging

See above myth. Nothing about CQRS says “thou shalt use NServiceBus”. It’s just not there. You’re merely separating infrastructure between handling commands and queries, but the how is quite varied. Don’t start with a bus until you prove you need eventual consistency.

Consistency models are a business decision because it directly impacts user experience. An eventually consistent model requires a different user experience than an immediate one, and this is not something you can just “slip in” to your users, or try to emulate. If you’re attempting to emulate immediate consistency in an eventually consistent model, you’re doing something wrong.

Myth #4 – Commands are fire-and-forget

How many business processes in your line of work are truly fire and forget? You typically need at least a synchronous acknowledgement that the command was received and accepted. If you’re doing an async send of the command, how do you notify the user? Email? Are they OK with this?

Instead, with commands that need heavy lifting to fulfill the request, we really have two things going on:

  • Accepting the request
  • Fulfilling the request

Accepting the request should be synchronous. Fulfilling need not be. But for the model of an asynchronous fulfillment, we still will likely need ways of correlating requests etc., and this is where you often see workflows/processes/sagas come into play.

Myth #5 – Read model needs to be built in an eventually consistent manner

Only when the business needs require eventual consistency does it need to be eventually consistent. How do we find this out? Probing and questioning. But not of the kind of “hey mr. business dood, can the read model be eventually consistent?”

Instead, we have to dig down on why we would need eventual consistency, and track those back to actual business needs. This is where imagining worlds without computers really helps. Human systems are inherently failure-prone, asynchronous and massively parallel. We just need to match our systems to how they actually work, not necessarily match human systems to how we built our applications.

Remember, as soon as you move to eventual consistency, your user experience must now deal with that fact that the operation the user just performed will not have its effects show up immediately. Additionally, you have to deal with failures in that area. What happens if your mechanism to build your read model fails or is slow? Does your user experience support those situations? If not, I don’t think you’re going to enjoy the support calls.

Myth #6 – CQRS lets you escape consistency problems and eliminate concurrency violations

Decidedly no on both counts. I’ve seen CQRS/ES systems scale horribly, mainly because in order to skip the problems of concurrency all commands and denormalization requests were flowed through a single-file line. Yes, forcing all commands to execute in single-file will eliminate concurrency problems. But now we’ve just forced ourselves into a serializable transaction isolation level.

On the read side, you can make your event handlers idempotent, but can they operate if items arrive out-of-order? Or arrive twice? De-duplicating events helps the latter, but I’ve seen teams miss out-of-order events again and again.

Denormalizing event handlers can be simple, but they are not the brain-dead code that I originally thought they would be. You just can’t escape concurrency.

Myth #7 – CQRS is easy

If it were easy, I wouldn’t see so many people with failed attempts to roll out a CQRS system. CQRS does not eliminate the need to understand what our business needs are. It might make it easier to realize those needs, but it’s just as easy to build the wrong system in a CQRS architecture as it is with n-tier.

Understanding business requirements are the hard part. Sure, we all have technical challenges. But for the CQRS sweet spot of task-based UIs and behavioral domains, that requires us to understand what the heck the business actually needs (versus wants).

Things get even more difficult with CQRS systems replacing legacy applications. In these situations, a wholesale rewrite is the most risky option you can take, and just having CQRS in your corner does not eliminate these risks.

The Silver Lining

All this being said, CQRS is a lovely architecture for separating two wildly different concerns. But don’t just throw every related CQRS concept at your application – defer these decisions until you’ve proven their need. You might just end up with something that actually fits the business needs!

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in CQRS, Domain-Driven Design. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Khalid Abuhakmeh

    I’ve heard Andreas Ohlund mention the problem of out of order events on a podcast but haven’t heard anyone talk about how to address the issue. Any chance you can write a blog post describing what steps and thinking you can take to handle such situations?

  • Rémi BOURGAREL

    Thanks for this post. Every time I need some info about CQRS I get a post talking about event sourcing, aynchronous command … CQRS is just one principle that enable SRP.

  • http://twitter.com/aliostad Ali

    Everything is possible but not everything is beneficial. I can understand that I “can” use CQRS without any of above, but would I “benefit” from choosing this pattern but go the classic way in implementation?

    Design is all about compromise. I pay the complexity price for choosing CQRS but for me it only make sense to go all the way to benefit from such design – unless you correct me with an example.

    Having said that, I think this is a great post promoting understanding related but different concepts.

    • Anonymous

      What does it mean to “go all the way”?

      • http://twitter.com/aliostad Ali

        Items 1, 2 and 3. Why would you want to separate your command and read models and then put them on the same transaction? Why would you not use Bus. Sure, you may design CQRS and delay the decision to use all above so that you may switch anytime you want, but I do not think this is a real-world example.

        • Anonymous

          I should probably elaborate more on these models. But “real world”? Are apps in production not real world?

          And nothing in CQRS says “asynchronous”. It’s just an orthogonal concern. I could do async + n-tier, or sync + CQRS, I’m just trying to point out that it’s a separate decision.

          • http://twitter.com/aliostad Ali

            I do not want to drag on the discussion here, but would you ever do one without the other)? Yes, you can but would you choose to (use CQRS+Sync)? And if so an example is helpful.

            It is like lemon grass. Yes, I can use it in any dish but the only dish I would use is Thai dish, it goes well with chilli, coconut oil and coriander.

          • Anonymous

            Would I choose? Yes, it’s in fact my first choice, but it’s worth elaborating on. It really comes back to user experience where this sort of stuff shows its real differences.

  • Bob D.

    Myth #8 – CQRS is just the latest trendy cargo-cult architecture on the block.
    …. Not a myth.

    • Anonymous

      lol well CQRS has only named an architecture that has been around for decades. You’ve probably built a CQRS system but didn’t have a name for it!

      • Christopher

        Also it’s a pattern rather than an architecture

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1174

  • Pingback: Distributed Weekly 169 — Scott Banwart's Blog

  • Pingback: Какими бывают репозитории? | Гулин Сергей

  • http://mathiasverraes.com Mathias Verraes

    >> If it were easy, I wouldn’t see so many people with failed attempts to roll out a CQRS system.

    Are you aware of any case studies or post mortems of failed attempts?

    • jbogard

      Not that I know of – these are clients that I’ve talked to personally.
      Of course, nobody calls for help if everything is unicorns and rainbows, so there definitely could be some confirmation bias on my end.