CQRS
Command Query Responsibility Segregation
Last updated
Command Query Responsibility Segregation
Last updated
CQRS (Command Query Responsibility Segregation) involves separating the mutation model from the query (look up) model.
When having multiple Bounded Contexts, querying data from them starts getting complex and heavy.
What types of solutions CQRS offers.
Commands represent transformations caused by business rules.
Like:
Transfer money to an account.
Enroll a student in a school.
Make an online purchase.
Emit a NF.
Its preferable to refer them as modifiers or mutators instead of commands.
Queries are done over data.
Like:
What is the account balance.
Which students got the higher grades in the 2° bimester.
What are the best selling products last month.
Be careful with data calculated on the run, all the time. Maybe they should be calculated on the Domain Model instead.
The objective would be to replicate the databases, and have one only for reading.
Ex.: Having mirrored Databases for Read and Write only.
Not necessarily, you must analyze the performance, the persistence model not always is optimized for querying.
If the objective is to store multiple non-structured projections, YES.
Use of:
Cassandra
MongoDB
HBase
Redis
CouchDB
When using simpler architectures, it is a lot more straight forwardd to access the Data base.
There is no real need to use CQRS, since JOIN
on tables are doable, there is probably only a single database.
In these more complex architectures, expecially when using Repositories, you shouldn't be using them for querying over data, due to:
Performance loss;
Excessive filters to be added to the Repository;
Unability to join data efficiently.
In these types of architectures, the essence is on how to query these distributed data.
API Composition
PatternOne way would be deriving/replicating to a second Read-only database, it is a cheap and fast way. So writes are done in a separate database.
But this still have the same problems as maintaining just one database, meaning, there will be too many JOIN
s on tables, the tables are probably not built for the bulk READ queries.
The better way is maintaining a separate database that will have Materialized Views
, which are tables specific for these bulk queries, that have data from all the different services gathered and flattened in one place.
It is also possible to use asynchronous and more resilient mechanisms, like publishing events and consuming them on a Queue
.
It is possible to update these Materilized View
synchronously during .
Use different patterns inside the project for accessing the database.
(like DAO
vs Repository
)
Create Snapshot for specific information.
Ex.: The bank will create snapshots of the balance so that it does not have to recalculate data since the beginning.
Have projection tables with consolidated data for reading only.
You can create intermediate tables that gather information, saving multiple joins to be done from the relational tables. (Kind of like a View)
Using materialized views.
Use the Database Views, but caches these results.
Must have a solution for reloading the data.
Separate the database for writing and for reading.
Using adequate database types for each purpose.
(like SQL
vs NoSQL
)