Temporal Queries and Point-in-Time State
A temporal query reconstructs entity or system state at a specified stream version or timestamp by selecting only facts accepted by that coordinate and folding them in order. It answers what was recorded then, while current-state query answers what is recorded now.
Problem
Why this pattern exists
Conventional current-state rows overwrite prior values. Logs may show requests but not accepted domain state, timestamps may use different clocks, and audit tables often omit reducer logic. Incident response then cannot reliably answer whether a decision was correct given information available at that moment.
Temporal correctness requires named coordinate. Stream version is precise within one aggregate. Global WAL position orders accepted writes across store. Event timestamp supports human time questions but equal or skewed clocks need tie-breaker. Effective business dates may differ from record time and should be explicit payload facts, not substituted for append order.
Design decisions
Make boundaries explicit
- 01
Choose temporal axis
Use stream version for aggregate reconstruction, durable log position for cross-stream processing boundary, recorded timestamp for operator questions, and domain effective date only when business model needs bitemporal meaning.
- 02
Fold with historical rules
Reducer and upcasters must interpret old facts consistently. Record policy version or decision inputs when reconstructing what system knew matters more than applying today's policy to yesterday's data.
- 03
Explain result with provenance
Return source event IDs, versions, and as-of coordinate with reconstructed state. A historical answer without boundary and evidence is hard to audit and easy to misread.
AllSource implementation
Apply pattern to durable Core history
AllSource Core supports point-in-time entity reconstruction and can seed replay from nearest eligible snapshot before applying later events. Query ordered entity events through /api/v1/events/query and use reconstruction endpoints for state questions. Core keeps stored history durable through WAL and Parquet rather than depending on application logs.
Expose as-of coordinate in API response and interface. For a decision audit, store event that records selected policy, input references, and outcome; temporal query can then reconstruct both state and evidence. Prime uses same pattern at application layer to trace recalled facts back to source events and reconstruct what agent memory contained before later corrections.
question: what was account-42 state before decision D-918?
boundary: stream version 318
snapshot: version 300
replay: versions 301..318
result: balance 5000, risk_tier "medium"
evidence: source event IDs returned with reconstructionFailure modes
Detect weak implementations early
Historical query uses current row plus old logs and disagrees with decisions.
Fix: Reconstruct from accepted domain events at explicit version or timestamp.
Equal timestamps produce unstable replay order.
Fix: Use stream version or log position as deterministic tie-breaker.
Today's policy is applied to old facts and called historical truth.
Fix: Record policy version and separate reconstruction from re-evaluation.
Production checklist
Ready when each statement is true
- Every temporal query names axis and inclusive boundary.
- Replay order has deterministic tie-breaker.
- Snapshots never include events after requested coordinate.
- Result returns source events and as-of metadata.
- Historical reconstruction and present-day re-evaluation are separate operations.
Related patterns
Continue through adjacent decisions
Snapshots and checkpoints
A snapshot stores derived aggregate state at a known point in its history; a checkpoint stores how far a consumer processed the event log. Both speed recovery, but neither replaces source events. Snapshot validity depends on reducer compatibility, while checkpoint validity depends on consumer identity and delivery semantics.
Read nextEvent replay
Event replay reads immutable events again in their original stream order and applies them to a new or reset consumer. Use replay to rebuild projections, reproduce historical state, test new reducers, or backfill derived outputs—never to re-trigger uncontrolled external side effects.
Read nextEvent schema evolution
Evolve event schemas by preserving stored facts, registering versioned contracts, making compatible additive changes, and translating old payloads at read time when semantics change. Never rewrite production history merely to match newest application model.
Read nextStore history once
