CQRS is not an architectural pattern

Rogelio Consejo
6 min readApr 24, 2024

Alright, I’ll be the one to say it — CQRS is not an architectural pattern; it’s an implementation detail. To be precise, it shouldn’t be regarded as an architectural pattern but rather a collection of solutions for persistence, although that doesn’t make for a catchy title.

Much like MVC (Model View Controller), which is more of a front-end design pattern than an architectural pattern, Command Query Responsibility Segregation (CQRS) has emerged with the aura of a transformative architectural principle. However, don’t be deceived.

While it’s possible to use it as an architectural pattern and perceive it as such, that might not be the best approach. Let’s explore why.

Something just doesn’t add up

CQRS as an Implementation Detail

One day, I was in the middle of a long spiritual learning session from a “chamán” in Catemaco, Veracruz, when, after a year of uninterrupted meditation, sustained by nothing but the air of inspiration and the nourishment of algorithms, I found myself in a shamanic vision, surrounded by a swirling mist that enveloped me in a gentle embrace.

The air was thick with the scent of ancient wisdom and earthy fragrances, hinting at the mystique of the realm I had entered. As the mist danced around me, it seemed to carry whispers of insight and knowledge from ages past.

Amidst this surreal atmosphere, a figure emerged from the mist — none other than Uncle “Bob” himself!

With a knowing twinkle in his eye and the faint scent of sandalwood lingering in the air, he imparted his wisdom: “Bricks are not the architecture of a house. The initial architecture is about use.”

Little did I realize that this mystical encounter would unveil the profound parallels between physical and software architecture, emphasizing the fundamental principle that true architecture must always serve the intrinsic needs of the system.

I was blind but now I see

After the mystical encounter, it struck me that positioning CQRS closer to an implementation detail for persistence, rather than an all-encompassing architectural principle, offers a more practical and adaptable approach.

Consider CQRS as the backstage magician of data persistence rather than the architect of the system.

When it comes to scalability, it’s like tailoring a suit — the domain guides us on where to make the cuts, ensuring a bespoke fit for each part of the system. Just as one size rarely fits all, it’s unlikely that a singular persistence solution will meet the diverse needs of a complex system. Embracing different persistence solutions for different parts not only makes sense but also opens the door for CQRS and its savvy strategies to work their magic in optimizing performance and efficiency when needed.

When adopting CQRS as an architectural pattern, the emphasis shifts towards treating the reading and writing of data as primary concerns, often preceding the domain and business logic.

As my rubber duck AI puts it: “The context and intent behind data operations, while important, are indeed secondary considerations within the scope of CQRS as an architectural pattern.”

What we really want, architecturally, is to be able to change out persistence strategy without having to rewrite the whole system. Thinking of CQRS as “architectural pattern” and commiting to it makes your system less flexible and more fragile. It treats your whole system as one big database.

So what you really want to do with CQRS is very simple: defer it.

Contextual Scalability and Domain Partitioning

Imagine a virtual marketplace where the needs of individual users, such as buyers and sellers, diverge in their essence and evolve at distinct paces.

We have users… and use cases…

By partitioning the system to align with these disparate needs, we can orchestrate tailored experiences that resonate with each user type. For example, you probably don’t store your configurations the same way you store your transactional data (some people do, I have seen it, and I am still trying to forget it ever happened), except maybe at the very beginning of development.

We tend to forget that config files are also a form of persistence, as well as environment variables, which means that a lot of developers don’t know that they are using more than one persistence already, but they do. And by the way, variables are also a form of short term persistence sometimes, specially in tests, but I digress.

In that sense, the persistence for the product catalog would not need to scale at the same time as the persistence for the user’s transactions. One could benefit from Command Query Responsibility Segregation more than the other, and earlier than the other. And even then, they could probably benefit from different kinds of CQRS implementations as one is going to be writing a lot more than the other, so they could benefit from being optimized differently.

And in this case, I picked two parts of the system which persistence implementation’s needs are easy to guess, but we cannot always guess correctly, so, again, flexibility and intent should come first, so that we can have code that we can test and adapt.

You obviously will write a lot more on the transactions side that you will do on the product catalog. And you are also probably be reading the catalog more than the transactions.

We start by thinking about the users, then the system’s responsibilities, then we test our system and adapt it, and eventually we probably will need CQRS. Or maybe there is an existing data intensive system and you want to make it faster… which is kind of the same story but starting from a later point.

So the first thing is the intent, and once we get down to the specifics and the pragmatics of the reality of what the system needs for reading and writing data for a specific part of it, then it makes sense to talk about CQRS.

So, what is CQRS then?

It is more a collection of solutions (design patterns?) for data handling.

In this journey through the realm of software architecture, we have discovered the magic of CQRS. By deferring its integration until we understand the realities of data operations, we become the master craftsmen tailoring a bespoke suit for the system.

No longer constrained by rigid architectural doctrines, we embrace the flexibility and adaptability that CQRS offers as a practical tool.

Just as a maestro composes a symphony to evoke distinct emotions, we orchestrate the integration of CQRS strategies to meet the unique needs of individual system components. So let us embrace this approach, optimizing performance and efficiency with its savvy strategies.

Remember, true architectural quality lies in the ability to change persistence strategies without rewriting the whole system. With CQRS, we defer, we adapt, and we unlock the true potential of our software architecture, but only if we keep it in its right place.

Also, don’t forget to eat vegetables. It’s crazy how healthy those things can be. Don’t believe me, ask your doctor.

--

--