Ordering and consistency
A projection applies changes in a defined order within one source and one read model, and a change becomes visible after a delay you can tune. This page states what order you can rely on and how long a change takes to show up.
Ordering
A projection applies the changes from one source to one read model in the order of their positions, whatever key the event is published under. A projection whose read models share one key applies every message of a source in order; see One read model for everything. Different read models are independent: their changes apply in parallel, in no order relative to each other.
There is no defined order across sources. A read model fed by the capture topic and a read-model topic, or by the event store and the capture topic, receives each source’s changes in order, but nothing orders a change from one source against a change from another.
Pinning a projection single-owner, with spring.ddd.cqrs.projections.<name>.distribution: single-owner, applies each source in one order across all of the projection’s read models.
It still does not order one source against another.
A message its error handler decides DEAD_LETTER on is applied after the messages behind it, so for that read model the order no longer holds; see What each outcome does to a read model.
A read model fed by several sources should not depend on their relative order: let each source set the fields it owns.
Eventual consistency
Read models are eventually consistent: a change is not visible the moment it commits.
A change becomes visible within the projection’s polling interval, spring.ddd.cqrs.projection.polling.interval (1 s by default), plus one polling interval of its source’s high-water mark, spring.ddd.messaging.high-water-mark.polling.interval (1 s by default) and up to two on PostgreSQL, plus the time the projection takes to apply what it read; see How quickly the mark moves.
With the defaults that is about 2 s per hop, where one hop is one projection the change passes through, reading its source.
A read-model topic on a database other than PostgreSQL is readable as soon as its change commits, so that hop costs only the projection’s polling interval.
Each projection in a chain adds a hop: a read model two projections downstream of an event becomes visible about 4 s after it on PostgreSQL, about 3 s on other databases.
Nothing wakes a projection when a change commits: it finds the change on its next poll.
Lowering either interval makes changes visible sooner, at the cost of more queries against the database from every instance.
spring.ddd.cqrs.projections.<name>.polling.interval sets one projection’s interval.
spring:
ddd:
cqrs:
projection:
polling:
interval: 1s # every projection
projections:
account-summary:
polling:
interval: 200ms # this projection only
messaging:
high-water-mark:
polling:
interval: 1s