Live Aggregations
Live aggregation replays events on demand to build the current aggregate state without persisting a read model.
Basic Usage
var order = await session.Events.AggregateStreamAsync<OrderSummary>(streamId);This loads all events for the stream and applies them through the aggregate's Create and Apply methods.
When to Use Live Aggregation
Live aggregation is best for:
- Infrequently accessed aggregates -- No need to maintain a persistent read model
- Always-current state -- No staleness, always reflects the latest events
- Streams with few events -- Low replay cost
- Testing and debugging -- Verify aggregate behavior
Version Cap
Replay only up to a specific version:
var orderAtV5 = await session.Events.AggregateStreamAsync<OrderSummary>(streamId, version: 5);Timestamp Cap
Replay only events before a specific time:
var orderAtTime = await session.Events.AggregateStreamAsync<OrderSummary>(
streamId,
timestamp: DateTimeOffset.Parse("2024-06-15")
);With Snapshots
If a snapshot exists for the stream, AggregateStreamAsync automatically uses it to optimize replay:
- Load the snapshot from
pc_streams - Only replay events after the snapshot version
- Return the hydrated aggregate
See Snapshots for details on configuring snapshot storage.
UseIdentityMapForAggregates
Polecat offers a performance optimization that caches aggregates in a session-level identity map when using FetchForWriting(). When enabled, subsequent calls to FetchLatest() within the same session will return the cached instance instead of re-querying the database.
opts.Projections.UseIdentityMapForAggregates = true;This is particularly valuable in CQRS command handlers that fetch an aggregate for writing, append events, and then need to return the updated aggregate state — avoiding a redundant database round trip.
WARNING
Only use this optimization if you are NOT mutating the aggregate outside of Polecat internals. This is safe with immutable event application patterns (Apply methods that set properties from event data).
TIP
Unlike Marten, Polecat defaults to lightweight sessions (no identity map tracking). This optimization adds aggregate-specific caching on top of lightweight sessions without switching to full identity map sessions.
Live vs Inline vs Async
| Strategy | Consistency | Storage | Performance |
|---|---|---|---|
| Live | Always current | None | Replay cost per read |
| Inline | Always current | Document table | Write overhead |
| Async | Eventually consistent | Document table | Background processing |

JasperFx provides formal support for Polecat and other Critter Stack libraries. Please check our