Collection runtime
Collection runtime
The collection runtime is the server half of every read and write. It compiles queries to SQL, evaluates policies, runs hooks, gates approvals, and records audit — all inside one decision path.
Query compilation
Client reads and writes arrive as structured operations, not raw SQL. The runtime compiles them against the compiled schema — joins, filters, and projections included — so tenant code never builds SQL strings.
Policy evaluation
Every operation is evaluated against the policies of the acting principal: row conditions narrow the SQL, redaction strips attributes, and approval config decides between direct, reduced, gated, or denied.
The mutation path
client.db.<collection>.mutate(values)
│ precisely typed root + explicitly included relationships
▼
┌─────────────────────────────────────────────┐
│ canonical mutation pipeline │
│ 1. before hooks validate + patch input │
│ (outside the transaction) │
│ 2. policy evaluation → direct / reduced / │
│ gated (approval) / denied │
│ 3. root + relationships commit atomically; │
│ bolt_collection_history and │
│ bolt_sync_outbox rows ride the txn │
│ 4. after hooks + task enqueue (settle) │
└────────────────────┬────────────────────────┘
│ bolt_sync_outbox
▼
every local replica - the client sends a precisely typed root and any explicitly included relationships through client.db.<collection>.mutate(values)
- before hooks validate and patch the candidate, outside the transaction — a refusal writes nothing
- policy evaluation narrows the operation and may gate it: direct, reduced, approval-required, or denied
- the root and every included relationship reconcile atomically — history and outbox rows in the same transaction
- after hooks run after the write has committed, and the outbox row written in the same transaction carries the change to every replica
The read path
A live query the replica can answer identically — a collection, a filter, a sort, a limit — never reaches the server; the client runs it against its policy-scoped local replica and the change log keeps that replica current. The read path waits for the network while the replica is still being built, and for the reads it deliberately declines: relationship expansion, free-text search, aggregates, and history, which live in this runtime rather than in the query compiler.
One transaction
An included relationship is its complete desired state: present rows are inserted or updated, stored rows absent from it are deleted, and explicitly included relationships synchronize recursively. Omitted relationships stay untouched. The root graph reconciles in one transaction, so either all submitted relationship state commits or none of it does; authorization, approvals, hooks, history, sync invalidation, and events remain in the same canonical mutation pipeline.
Related guides
The authoring surface is Collections ; writes travel on the command channel, and the sync engine carries committed changes outward.