Search code examples
cqrs

Designing the query layer in CQRS


I have been studying up on microservices and in particular the CQRS pattern presented well by this video. I think the command part is easy to understand for me as long as I embrace the eventual consistency and fine with it. However, what should happen when you do a simple query against the denormalized query layer using its API. I am thinking this way because you will probably do lazy loading of denormalized data to the query layer as the queries come right? Especially if that data you are querying for is really an aggregation of data scattered all across micro services, do you have to resort to a massive orchestration of firing fetch data event with some sort of context ID, and all microservices in turn publish their data with the same context ID so that denormalizer can listen and fill the aggregated data to its layer and finally respond back to the client?


Solution

  • What you described is actually API composition pattern - https://microservices.io/patterns/data/api-composition.html

    In CQRS, a separate DB will be used for queries. The result will be directly retrieved from this dedicated DB.

    CQRS generally is combined with event souring pattern. (https://microservices.io/patterns/data/event-sourcing.html) That means any state change in the system will be represented by an event.

    In the query service/logic, you need to subscribe to all the interested events and update data in the query DB accordingly in the event handler. Thus the data in query DB is eventually consistent with the data in command-side DB.
    (https://microservices.io/patterns/data/cqrs.html)

    CQRS makes querying easier/more efficient and improve separation of concerns. However, as you can see, it is more complicated to implement than API composition, and it has an innate issue - replication lag - the data in query DB may not reflect the latest state. So it is generally recommended to use API composition if possible, use CQRS only when you must.