CQRS / DDD + Event Sourcing. Can the ReadModel read itself

cqrsdomain-driven-designread-model

This is a question for those times you are creating the read model by event handlers.

The question comes down to : How can a Event Handler draw from other sources of information than what is contained in the handled event itself to construct a read model?

I have two aggregates, Person and Address. A person can be associated to different addresses (Home, Work, etc.)

So I have a read model table Addresses (ID, line1, line2, line3, etc.)

I also have a read model table PersonAddresses (PersonID, AddressID, line1, line2, line3) – Duplicated, denormalized data.

  • When an Address is created, I dispatch an event AddressRegistered with the address info (ID, Line1, Line2, etc.).

  • When an Address is associated to a Person, I dispatch an event AddressAssociated (with the PersonId, AddressId).

Then, I want to create the readModel.

  • When I receive a AddressRegistered event, I add an entry into the Addresses read model table.

  • When I receive a AddressAssociated event, I want to add an entry into the PersonAddresses read model table.

Though, I would like to have the address info as well (Line1, Line2, Line3) in the PersonAddresses table as my clien application will use it this way. But this info is not contained in the AddressAssociated event. This event only contains PersonID and AddressId.

What is the most recommended way of getting that information (Line1, Line2, Line3) for the associated Address in the AddressAssociated event Handler in order to populate the PersonAdresses read model table?

  • In the domain, attach the address info (Line1, Line2, …) to the AddressAssociated event so that it can be directly added into the PersonAddresses table ? That would require a domain service as it would need to look up multiple aggregates. (Address and Person are two aggregates)
  • When adding entries in the PersonAddresses, retrieve the information beforehand from the Addresses read model table? Is it recommended that the read model read itself (eventual consistency, etc.) ?
  • Something else?

Best Answer

You are allowed to create your read model projections as necessary, and you can either read the current read model state to update it, or, you can set up a pipeline where you read & update internal read model state, and from that (re)create the read model projections.

In some sense, you are always updating your read model picture of the world based on the last picture of that world + the effect of applying the next event. So, reading the read model is natural.

However, any way you do it, you have to be sure to consume the events (apply the events from the event source/log to the read model) in (the proper) order and using enough transactional atomicity so that downstream consumers always see a complete view of the state, which is either 100% the old state before applying an event, or 100% the new state after applying an event.

The eventual consistency means that when incoming events cease for a short while, the read model pipeline catches up. However, it would be bad to expose via in the read model, an inconsistent state (a state that never was a true picture of the world) say in which, either some change is only partially applied to the read model projections, or the effects of a later event is shown before the effects of an earlier one; this even if the state eventually converges on a true picture of the world.


You are still allowed to read the read model during update of the read model from the events in the event log.

However, there are some proponents of event enrichment, in which you do what you're saying for option 1; see: http://www.lavinski.me/generating-read-models-with-event-sourcing/, https://seabites.wordpress.com/2013/06/09/event-enrichment/

I think I'd still see prefer to see this as a function of the read model in generating its denormalized projections rather than a domain function, since it is not really a business function per se, but rather one of creating the right view, and keeping it wholly in the read model alone will decouple your command and query more from a maintenance point of view.

Related Topic