76 lines
2.0 KiB
Markdown
76 lines
2.0 KiB
Markdown
---
|
||
name: "Adr 0006 Event Store Append Only"
|
||
description: "Append‑only, ordered, idempotent event store invariants"
|
||
depth: 2
|
||
links: ["../index.md", "../modules/core-events-submodule-spec.md", "./adr-0005-persistence-choice.md"]
|
||
---
|
||
|
||
# ADR-0006: Event Store Append-Only & Ordering Invariant
|
||
|
||
**status:** accepted
|
||
**date:** 08.05.2026
|
||
**deciders:** Kami
|
||
|
||
---
|
||
|
||
## context
|
||
|
||
The system relies on an append-only event log as the single source of truth. Replay correctness, session reconstruction, and deterministic projections all depend on strict ordering and immutability of persisted events.
|
||
|
||
Without enforced guarantees at the storage layer, higher-level invariants (projection determinism, replay correctness) cannot be trusted.
|
||
|
||
This ADR formalizes storage-level constraints for all EventStore implementations.
|
||
|
||
---
|
||
|
||
## content
|
||
|
||
The EventStore MUST enforce:
|
||
|
||
### 1. append-only semantics
|
||
|
||
* events cannot be updated or deleted
|
||
* event_id is immutable and unique per event
|
||
|
||
### 2. idempotency
|
||
|
||
* repeated append attempts with same event_id MUST be ignored or rejected safely
|
||
* duplicate events MUST NOT be stored
|
||
|
||
### 3. per-session ordering
|
||
|
||
* sequence MUST be strictly monotonically increasing per session_id
|
||
* ordering MUST be total within a session stream
|
||
|
||
### 4. causality preservation
|
||
|
||
* causation_id and correlation_id MUST be preserved as metadata only
|
||
* they MUST NOT affect ordering
|
||
|
||
### 5. deterministic read model
|
||
|
||
* read(session_id) MUST always return events in sequence order
|
||
* read consistency MUST not depend on implementation timing
|
||
|
||
---
|
||
|
||
## consequences
|
||
|
||
**positive:**
|
||
|
||
* guarantees replay correctness foundation
|
||
* enables deterministic projection logic
|
||
* simplifies concurrency model (append-only reduces state conflicts)
|
||
* allows multiple backend implementations (sqlite, in-memory)
|
||
|
||
**negative:**
|
||
|
||
* no event mutation allowed (requires compensating events instead)
|
||
* stricter implementation requirements for persistence engines
|
||
* potential write amplification in correction scenarios
|
||
|
||
---
|
||
|
||
## status
|
||
|
||
accepted |