Skip to content

Watching Read Models

Watching a read model gives a client a stream of changes as Chronicle applies projections and reducers. Use it for live dashboards, cache invalidation, background coordination, and interfaces that should update without polling.

Not every Chronicle client exposes the watch API yet. The examples below show the clients that currently do.

Each change tells you:

FieldMeaning
NamespaceThe Chronicle namespace where the change happened
KeyThe read model key that changed
Read modelThe current state after the change
RemovedWhether the instance was removed

The change carries the current read model state, not the previous state. If you need to detect a transition, keep the last value you saw for each key or react to the domain event with a reactor.

The read model type must be registered before you subscribe.

using var subscription = eventStore.ReadModels
.Watch<Order>()
.Subscribe(changeset =>
{
if (changeset.Removed || changeset.ReadModel is null)
{
return;
}
Console.WriteLine($"{changeset.ModelKey}: {changeset.ReadModel.Status}");
});

Dispose, cancel, or break out of the subscription when the caller no longer needs updates. Long-lived subscriptions should be owned by a service with an explicit lifetime.

Filter as close to the subscription as the client allows. This keeps application code focused on the state changes it actually cares about.

using var subscription = eventStore.ReadModels
.Watch<Order>()
.Where(changeset => changeset.ReadModel?.TotalAmount > threshold)
.Subscribe(changeset =>
{
Console.WriteLine($"{changeset.ModelKey}: {changeset.ReadModel!.TotalAmount:C}");
});

Filtering happens client-side. If the client subscribes to a busy read model, the server still sends matching change notifications for that read model type.

Use read-model watching when:

  • A UI needs pushed updates.
  • A cache should invalidate or refresh when state changes.
  • A background service reacts to state changes instead of raw events.
  • The consumer can manage a long-running subscription.

Prefer current-state reads when:

  • The caller only needs a value once.
  • The process cannot own a long-running subscription.
  • The reaction should be based on the original event rather than derived state.