Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Overview

Understand how journals and Session stores make execution durable and restorable.

developer

Harness persistence has one authoritative ordered ledger per session and a derived catalog for cheap listing. The journal stores Enduring events, command intent records, lease fences, and private gate-preparation records. Large envelopes are stored in the session’s content-addressed blob prefix and the ledger receives an integrity-checked pointer.

Durable boundaries

There are three different guarantees to keep separate:

SurfaceGuaranteeTypical consumer
journal.SessionJournal.Appendone serialized durable frame and sequenceruntime writer
journal.EventReplayerordered public or privileged events, cold onlyhistory/status reader
sessionstore.Catalogderived projection, repairable, no ledger cursor for readssession picker

The catalog is never the source of truth. A successful journal append may be followed by a best-effort catalog update; RepairCatalog folds the ledger when the projection is missing, stale, or corrupt.

Two read views

OpenEventReplayer returns public events only. It filters commands, fences, private gate payloads, and internal visibility. Restore and storage maintenance use the privileged OpenInternalEventReplayer or OpenInternalRecordReplayer seam. The full record view is required to rebuild idempotency and delegate-delivery indexes and to recover gate payloads.

%%{init: {"theme":"dark"}}%%
flowchart LR
    W[Session runtime] -->|Append| J[SessionJournal]
    J --> L[Ledger: sessions/UUID]
    J --> B[Blob store for large frames]
    J --> C[Catalog UpdateOnEvent]
    L --> P[OpenEventReplayer: public events]
    L --> I[OpenInternalRecordReplayer: events commands fences private gates]
    P --> H[History and catalog repair]
    I --> R[Restore and index hydration]
    C --> K[ReadMeta / ListSessions]

Ownership flow

Every live writer holds a session lease. OpenJournal immediately appends a FenceRecord with that lease’s epoch, then hydrates idempotency state before returning. Appends are serialized under a mutex and fenced at the tracked ledger tip. GC also requires the lease and must be serialized with appends.

%%{init: {"theme":"dark"}}%%
sequenceDiagram
    participant S as Store
    participant L as Lease
    participant J as Journal
    participant D as Ledger

    S->>L: AcquireLease(sessionID)
    S->>J: OpenJournal(sessionID, lease)
    J->>D: Fence(epoch) at current tip
    J->>D: hydrate idempotency and delivery indexes
    J-->>S: ready SessionJournal
    S->>J: Append(record)
    J->>D: CAS append at tracked tip

Choose a surface

Source and proof

← back to documentation