Projecting Read Models
For the read models to work, the system has to project changes from the command execution model to all its read models. This concept is illustrated in Figure 8-12.
![]() |
Figure 8-12. CQRS architecture
The projection of read models is similar to the notion of a materialized view in rela‐ tional databases: whenever source tables are updated, the changes have to be reflected in the precached views.
Next, let’s see two ways to generate projections: synchronously and asynchronously.
Synchronous projections
Synchronous projections fetch changes to the OLTP data through the catch-up sub‐ scription model:
• The projection engine queries the OLTP database for added or updated records after the last processed checkpoint.
• The projection engine uses the updated data to regenerate/update the system’s read models.
• The projection engine stores the checkpoint of the last processed record. This value will be used during the next iteration for getting records added or modified after the last processed record.
This process is illustrated in Figure 8-13 and shown as a sequence diagram in Figure 8-14.
![]() |
Figure 8-13. Synchronous projection model
![]() |
Figure 8-14. Synchronous projection of read models through catch-up subscription
For the catch-up subscription to work, the command execution model has to check‐ point all the appended or updated database records. The storage mechanism should also support the querying of records based on the checkpoint.
The checkpoint can be implemented using the databases’ features. For example, SQL Server’s “rowversion” column can be used to generate unique, incrementing numbers upon inserting or updating a row, as illustrated in Figure 8-15. In databases that lack such functionality, a custom solution can be implemented that increments a running counter and appends it to each modified record. It’s important to ensure that the checkpoint-based query returns consistent results. If the last returned record has a
checkpoint value of 10, on the next execution no new requests should have values lower than 10. Otherwise, these records will be skipped by the projection engine, which will result in inconsistent models.
![]() |
Figure 8-15. Auto-generated checkpoint column in a relational database
The synchronous projection method makes it trivial to add new projections and regenerate existing ones from scratch. In the latter case, all you have to do is reset the checkpoint to 0; the projection engine will scan the records and rebuild the projec‐ tions from the ground up.
Asynchronous projections
In the asynchronous projection scenario, the command execution model publishes all committed changes to a message bus. The system’s projection engines can subscribe to the published messages and use them to update the read models, as shown in Figure 8-16.
![]() |