Getting a Collection of Instances
Sometimes you need the exact current state of every instance of a read model: a small report, an integrity check, a back-office export, or a diagnostic script. Chronicle can rebuild the whole collection by replaying the events that feed that read model.
This is a strong-consistency operation. It is also proportional to event history, so it is not the default tool for hot list views or large data sets.
Read all instances
Section titled “Read all instances”Use collection replay when the result set is small enough to fit comfortably in memory and the caller needs state that includes every event appended so far.
var accounts = await eventStore.ReadModels.GetInstances<Account>();
foreach (var account in accounts){ Console.WriteLine($"{account.Name}: {account.Balance:C}");}alias MyApp.ReadModels.Account
{:ok, accounts} = Chronicle.ReadModels.get_instances(Account)
Enum.each(accounts, fn account -> IO.puts("#{account.name}: #{account.balance}")end)const accounts = await store.readModels.getInstances(Account);
for (const account of accounts) { console.log(`${account.name}: ${account.balance}`);}Kotlin currently exposes single-instance read-model lookup only, so collection replay is not shown for that client.
Filter in memory
Section titled “Filter in memory”Replay returns every instance. Apply language-native filtering after the read, and keep that in-memory cost in mind.
var accounts = await eventStore.ReadModels.GetInstances<Account>();
var highValueAccounts = accounts .Where(account => account.Balance > threshold) .OrderByDescending(account => account.Balance) .ToList();
Console.WriteLine($"Found {highValueAccounts.Count} high-value accounts.");alias MyApp.ReadModels.Account
{:ok, accounts} = Chronicle.ReadModels.get_instances(Account)
high_value_accounts = accounts |> Enum.filter(&(&1.balance > threshold)) |> Enum.sort_by(& &1.balance, :desc)
IO.inspect(high_value_accounts, label: "High-value accounts")const accounts = await store.readModels.getInstances(Account);
const highValueAccounts = accounts .filter((account) => account.balance > threshold) .sort((left, right) => right.balance - left.balance);For large result sets, query the materialized sink directly or use a product-specific query model instead of replaying everything and filtering afterward.
Limit the replay
Section titled “Limit the replay”You can cap the number of events Chronicle processes. This can make diagnostics faster, but it can also return incomplete state if the cap cuts off events that matter.
var orders = await eventStore.ReadModels.GetInstances<Order>(eventCount: 1_000);
Console.WriteLine($"Replayed {orders.Count()} orders from the capped history.");alias MyApp.ReadModels.Order
{:ok, orders} = Chronicle.ReadModels.get_instances( Order, event_count: 1_000 )
IO.puts("Replayed #{length(orders)} orders from the capped history.")const orders = await store.readModels.getInstances(Order, 1000n);
console.log(`Replayed ${orders.length} orders from the capped history.`);Use an event-count cap for historical analysis, back-testing, or bounded diagnostics. Do not use it when the reader expects the current truth.
When to use this
Section titled “When to use this”Use collection replay when:
- You need a strongly consistent report over all current instances.
- The read model population is small.
- You are running an administrative or diagnostic task.
- You are validating data derived from the event log.
Prefer materialized or database-native reads when:
- The page is user-facing and called frequently.
- You need server-side filtering, sorting, or paging.
- The read model has many instances or long histories.
- Eventual consistency is acceptable.
Related topics
Section titled “Related topics”- Getting a Single Instance - Replay one read model instance by key
- Getting Snapshots - Inspect historical state for one instance
- Watching Read Models - React to read model changes
- Materialized Read Models - Read sink-stored projections with paging