CQRS explained with different flavors

Sameh Muhammed - Oct 19 '22 - - Dev Community

Let's start with use case

Let's say you have an monolithic online store application as image below.

Image description

The Problem

this application with this architecture was serving a certain number of visitors in a good way, but after a while and this application became famous and be visited by huge number of users daily, you found that requests took a lot of time to be served and you may found some requested failed or dropped by system regarding to load upon system.

We were talking regarding to customers only, but as online store you have to provide reports to managements and to service providers as well and these reports may cost long running transactions and expensive read queries.

So you have a problem and you need a solution.

The Solution

So, you decided to start thinking about enhance the system from the bottom (database layer), You opened your toolbox of how to improve DB queries and found solutions like indexing, partitioning and replicating then started applying these solutions in right way and move them to production.

Image description

Side effect

After applying these tactics you surprised how queries are fast now and you gained some performance for your users, but after a while you found that all write statements now took a lot of time comparing before our enchantment, why that?

Guess what, all solutions we applied above it boost application queries, but when it comes to write queries like INSERT/UPDATE, they have a side effect.

explanation

Multiple indexes up on tables boost reading performance but in case of writing it harms, cause now you have to write to disk and also to index , then re sorting the indexes after write operation. and in case of partitioning DB have to know which partition this insert belongs to or update operation may requires move records from one partition to another not just writing new values.

CQRS to the rescue!

Command Query Responsibility Segregation, an architectural design comes to solve this issue, it tells you that, you either performs Command (INSERT/UPDATE) or asking a Query (SELECT), and each of them has its' own tuning strategies, so starting from this point why not to split them (Segregate Responsibility).

Image description

How this save our back?

As we have one database for Command/Writing operations and one for Reading/Query, and you are right you now can apply whatever performance tuning you need upon each one without affecting other ones.

By same concept also to solve reporting service dilemma, you can provide databases for your customers to serve their commands/queries which is known by OLTP (Online transaction processing), and another database to serve complex and long transactions for reporting purpose which if known by OLAP (Online analytic processing).

Image description

Nothing for Free!

But this is not for free, there is a cost for every thing. By splitting your databases you have to deal with data synchronization between Write database and Read one, which when successful write operation be performed on Write database it have to be moved to Read database also so that customers can read it, and you have to accept what called Eventual Consistency.

What is Eventual Consistency?

Regarding to splitting the responsibilities DB promises you that your data will be reflected to Read database but it can't promise you that all Read operations will read the most updated value regarding to synchronization time , may be your application accept this kind of problems and may not but you have to be aware of consequences.

Image description

CQRS with different flavor

CQRS comes with another way of thinking regarding to writing methods, which that you have to consider it when writing methods to separate logic that querying/read from that changes object state/value, by doing so you have single responsible, predictable, testable, and maintainable blocks of code.

Resources

IF YOU LIKED THE POST, THEN YOU CAN SUPPPORT SUCH CONTENT WITH A CUP OF COFFEE, THANKS IN ADVANCE.

Buy Me A Coffee

. . . . . . . . . . . . . . . . . . . . . . . . . . . .