Event Sourcing
Why CortexDB stores raw, immutable events as the source of truth instead of LLM-rewritten summaries.
Event sourcing means storing every interaction as an immutable, append-only event — the raw message, the timestamp, the actor, the scope — and never overwriting or rewriting it on the write path. Summaries, embeddings, and knowledge graphs are derived artifacts: built asynchronously, replaceable, and never on the write path.
Why it matters
The common fix for lost context is to compress past conversations into LLM summaries. That's lossy — every rewrite drops information, and by the third conversation the agent recalls an interpretation of an interpretation. CortexDB keeps the raw event as the source of truth. If a better embedding model ships next year, CortexDB re-embeds from raw events — a summary-based system can't, because the original is gone.
The log is the source of truth
A write does exactly one durable thing: it appends an event to the WAL (fsync'd by default, so an
acked event survives power loss; ~10 ms at the durable accept point with ?wait=captured). Everything else —
embedding, extraction, consolidation, synthesis — runs asynchronously off the log.
Because the log is immutable, derived views are deterministic functions of (events, derivation_version),
which unlocks:
- Reproducibility — same log + same extractor version → byte-identical derived state.
- Reversibility — fix a bad consolidation by dropping the derived view and replaying; no data loss.
- Auditability — every fact/belief/paragraph carries a
supportschain back to raw events. - Compliance — GDPR erasure redacts or hard-deletes events, then re-derives downstream. See Erasures.
A read never blocks on extraction — if the consolidator is behind, recall returns from the indices that are caught up.
A write on the wire
POST /v1/experience
Authorization: Bearer <PASETO>
X-Cortex-Actor: user:alice
Content-Type: application/json
{
"scope": "org:acme/dept:eng/user:alice",
"modality": "conversation",
"content": { "kind": "message", "role": "user", "text": "Priya from Acme wants to renew next quarter." },
"idempotency_key": "slack:C123:T456:1747293720"
}The server appends one event and returns 202 with event_id, status, wal_offset, and a
lifecycle_stream URL you can subscribe to. (The lifecycle_id appears in the SSE event data, not in
the write response.) The idempotency record survives restarts, so a retry after a crash replays the same
event_id (replayed_from_idempotency: true). The original text is preserved verbatim — not summarized.
What it enables
- Replay — ship a better embedder/extractor and rebuild derived state from the log.
- Audit — walk the
supportschain to the immutable messages behind any claim. - Honest forgetting —
/v1/erasuresdeletes/redacts source events and re-derives downstream, so deleted content is provably absent from derived views (no residue in summaries).
FAQ
Does event sourcing make writes slow? No — a write appends to the WAL and returns an fsync'd ack in
~10 ms (?wait=captured), flat in payload size. Extraction/embedding/consolidation run asynchronously.
Can derived views be rebuilt from the log? Yes — derived views are deterministic functions of the log + extractor version, so vectors, BM25 indices, facts, beliefs, and understanding can all be rebuilt by replay.
How does it relate to bi-temporal memory? The log records when CortexDB learned a claim (recorded time); bi-temporal facts additionally record when it was true (validity time).