ADR-0003: Source-of-truth and consistency model
ADR-0003: Source-of-truth and consistency model
Status
Proposed — gated on a spike (POC 4 Projection Engine / POC 5 Serving Store). Must not be marked Accepted until the spike runs and its result is recorded here.
Date
2026-06-24
Context
This is the decision the entire kernel rests on, and the source pack is internally ambiguous about it. Three of its claims cannot all be true under a naive design:
- “The Serving Store is a projection, not the sole truth … disposable / rebuildable from data products + statements + events + authority rules” → implies pure derivation.
- “Read-your-write: immediate or < 1s” and “simple action execution p95 < 250ms” → implies synchronous current state.
- “Projection lag normal < 5s” → implies asynchronous projection.
If the Serving Store is purely derived asynchronously from an event log, read-your-write is not immediate. Pure event-sourcing of an operational transactional store is the classic trap that sinks systems of this kind. Notably, Palantir’s actual Object Storage v2 is not pure event-sourcing — it is a transactional current-state store with a separate history/lineage path.
This decision interacts with: ADR-0004 (statement-backed attributes need conflict resolution at projection time), ADR-0011 (precomputed topology projections), and ADR-0013 (offline conflict-as-outcome relies on expected-version against current state).
Decision (proposed)
Hypothesis to test: an Action commits the event/statement log and the authoritative current-state row in one transaction (Postgres). Read-your-write is served immediately off current state. Only secondary indexes — search, topology materializations, spatial, scenario overlays — are asynchronous projections with measurable lag. “Rebuildable from the log” is a recovery and audit property, not the steady-state read path.
Falsification bar: if a synchronous event-log + current-state dual-write cannot hold p95 < 250 ms at 1M entities and 1K actions/min, fall back to CQRS with an explicit read-from-log (or session-pinned) path for read-your-write.
The spike must also answer: for statement-backed attributes (ADR-0004), does authority/conflict resolution run inside the write transaction or in the async projection, and what is the read-your-write guarantee for those specifically?
Alternatives Considered
Pure event-sourcing / CQRS
Truth = log only; Serving Store 100% derived async; read-your-write faked.
- Cons: maximal flexibility, maximal operational complexity, hardest to keep read-your-write honest.
- Held as the fallback, not the default.
State-primary, log-as-audit
Truth = current-state store; log is an audit side-effect, not the rebuild source.
- Cons: weakens “rebuildable from log” and statement-replay guarantees that ADR-0004 and history features depend on.
- Rejected as the default because it gives up replay/rebuild, but it is effectively what the hypothesis degrades to if rebuild is never exercised — the spike must keep rebuild real and tested.
Consequences
- Until the spike runs, downstream work assumes the hypothesis (sync state + async secondary indexes) but must not hard-code assumptions that only hold under it without flagging them.
- The spike is a freeze gate: no architecture freeze while this is Proposed.
- Whichever way it resolves, the resolution is recorded by editing this ADR’s Status to Accepted and appending a “Spike result” section — or by superseding it if the result invalidates the framing.