Learn Search docs

Data plane

The data plane is where facts live. Control plane (Yard) decides infrastructure; data plane runs your app and the Camp’s durable runtime. If the Yard is down, camps keep serving — they just cannot re-place that day.

Why event sourcing is the foundation

BenefitWhat you get
RecoveryCrash mid-deploy or mid-workflow → replay rebuilds exact state
AuditEvery infra change and credential issuance is an ordered fact
Time-travelReconstruct as-of; diff two points (hobo inspect)
DeterminismDurable workflows replay over cached step results

One log, two folds

FoldPurpose
Write model (aggregate)Authoritative state for invariant checks inside a single-writer actor
Read model (projection)Rebuildable views for queries, dashboards, reactive UI

Both fold the same append-only event log. Snapshots are caches, never sources of truth. Snapshot ahead of head → hard error (SNAPSHOT_AHEAD).

Commands → past-tense facts

  1. Commands enter at a boundary (HTTP, MCP, workflow step) — they are not stored as events.
  2. Aggregate decide runs pure business rules against folded state.
  3. Aggregate emit past-tense facts.
  4. Append uses expectedSeq (optimistic concurrency) and optional fenceToken (lease fencing).
  5. Optional stageEffect stages queue/timer/outbox work for the same durable transaction.
  6. After commit, live subscribers wake; network dispatch of staged work is at-least-once.

Default durable store

Camp EventStore defaults to a single-owner SQLite partition behind ports:

PropertyDetail
Stream headRevision + owner_epoch on a head row — not COUNT(*)
PositionsDatabase-local bigint for catch-up (EventPosition)
CheckpointsDurable subscription positions
Atomic effectsDomain events + staged work in one commit
Scale modelAdd partitions; not multi-writer NFS WAL

Details: EventStore reference · Durability tests.

Reactivity

Default reads are subscriptions over materializations (replay-then-live). GraphQL facades and point lookups are escape hatches over the same models. Session consistency is the usual default; stronger/weaker levels are entity-configurable.

Upcasters & quarantine

Event bodies evolve via forward-only upcasters. Poison events produce *.Quarantined facts so folds skip deterministically instead of wedging forever. Crypto-shred / erase rebuilds projections without rewriting history bytes in place.

What is not the event log

DataHome
Streamer frame bodiesStreamer journal (tokens, logs, progressive UI)
Authoritative-external provider DBsExplicit escape hatch with staleness labels
Blob/object payloadsBucket resources — store refs in events

Multi-aggregate work

Cross-aggregate operations are eventually consistent by design. Use sagas/choreography (events library) and correlation ids — do not invent a distributed transaction across aggregate streams.

Architecture · Control plane · Aggregates testing · Runtime ports