DataEntities, stores and migrationsDetails
System tables
On this page
The runtime needs tables of its own, for example to hold events until
they are delivered. Jadpo generates them, names them with the prefix
jadpo_, and keeps them in the migration snapshots like any entity, so
drift in them fails jadpo check too.
Tables in every store that holds an entity
The tables that must commit with an action's own writes go in each store an action writes, so an action's outbox and delivery records sit beside the writes they commit with. Jadpo gives them to every store that holds an entity, since any of them can be written:
| Table | Holds | Described in |
|---|---|---|
jadpo_outbox |
Each event an action emitted, with its trace context and how deep in a chain it is | Background work |
jadpo_deliveries |
Each event's delivery to each subscriber: status, attempts, next attempt, last failure, and while a circuit breaker holds it, its connection and time held | Background work |
jadpo_handled_deliveries |
Each delivery a subscriber's action handled, committed with its writes in the store it writes | Background work |
jadpo_idempotency_keys |
Each idempotent request's key, digest and stored response | Idempotent writes |
jadpo_operator_actions |
What an operator did to a delivery with jadpo deliveries: when, which action, the item and its state then, the operator's name and the database role |
Background work |
jadpo_circuit_breakers |
Each connection's circuit breaker over the deliveries beside it: its state, the run of failures, when it opened, its pauses and probe, and when its alert was raised | Background work |
A subscriber's record that it handled a delivery goes in the store the subscriber writes, committing with its writes, and refers to no table in another store (Delivery: at least once, safe to repeat).
An action with several changing calls keeps a record of them (Several changing calls in one action):
jadpo_step_records: each run's key, action, build, step shape, first start, the generation of the runner holding it, whether it diverged, and when the alert on unfinished records was raised for it;jadpo_steps: each step's operation, its request's fingerprint, when it was sent and its sealed answer.
They go in the store such an action writes, or events: { store: }'s,
only where one is kept. A resumable single keyed changing call with an
existing record store uses these tables for dispatch details only, with
no request fingerprints or encrypted answers, so the provider's safe key
window also bounds its retries (External services).
Tables for sign-in
Sign-in reads a credential with its caller's record in one statement, so these tables go in the store of the entity they belong to (Sign-in and identity). Secrets in them are kept only as verifiers: a verifier is a one-way digest that Jadpo can check a secret against, but can't turn back into the secret.
jadpo_sessions, browser sessions and API tokens: each one's user, the verifiers of its token and a browser session's CSRF token, and when it started and ends. Only in the store the principal's user entity lives in.jadpo_service_keys: each key's service, its verifier, and when it was issued and expires. Only in the store its service entity lives in.jadpo_passkeys: each passkey's user, its credential ID, the user handle its device keeps and theWebAuthnCredentialit is; andjadpo_passkey_challenges: each ceremony under way, by its challenge's verifier, with what it is bound to and when it expires. Beside the sessions they start.jadpo_sign_in_requests, for magic links: one row per address, by its digest, with the latest link's and code's verifiers and the counts the limits read. Beside the sessions they start.jadpo_sign_in_links: each way in and subject a first sign-in linked to a user, whenon_first_sign_in:decides an external token's first sign-in (A person the app has not seen). Only in the store the principal's user entity lives in.
The audit trail's table
An audited entity's history commits with the changes it records, so it
goes in the store the entity lives in, created when an entity there has
an audit: (Audit trail):
jadpo_audit: each change to an audited record, by the entity's born name, the record'sidand its place among the record's changes; when it was made, what kind of change, who made it, through which action, request and trace, and each changed field before and after as text, with the encoding that was written in. Rows are only ever added, then deleted when the entity's audit retention ends, or with their record when erasure deletes it.
Tables for schedules and other state
Schedule state, each schedule's lease included, goes in the store
schedules: { store: } names in app.jadpo, or the only store when there
is one (Schedules):
jadpo_schedules: each schedule's next due time, lease and last tick (a time the schedule was due to run);jadpo_schedule_runs: each run and skipped tick.
They are created when a schedule is declared, with
jadpo_operator_actions for what operators did to those runs.
Other features that only keep state name their store the same way
(flags: { store: main }), and with several stores a missing one is a
compile error naming the feature. The flags keep jadpo_flags, each
flag's state, and jadpo_flag_changes, each change jadpo flags made
and who made it (Feature flags). Other runtime state (multi-step call
records and batch runs beside the outbox, OAuth grants, poll state, and
webhook and queue de-duplication) follows the same rules and is always in
a database, never a cache
(Built-in services).
Every store holding runtime state, including a store holding only AI
usage, also keeps jadpo_housekeeping: the owner, lease and last completed
hourly cleanup pass (Background work). It is
generated and migrated with the other system tables.
A store whose entities have File fields keeps jadpo_files, how many
fields hold each stored file, which a trigger on each table with a File
column keeps as rows change; it is how a file's bytes are deleted once no
record holds them (Deleting and erasing).
Its migration makes the trigger, and counts the files existing rows hold.
The manifest holds a system_table node for each.
jadpo_migrations, which jadpo migrate apply keeps, is the runtime's
own and in no snapshot.
Encodings in system tables
A system table that keeps a value beyond a request records the encoding
it was written in, an encoding smallint, so a later release reads it
by the form it has
(Changing a standard type's encoding).
Those values are the outbox's payload, a passkey's credential, and a
batch run's saved values and key:.
The runtime always writes an encoding, but the column may be NULL, for a
row kept before encodings were recorded. A migration adds it to a table
that may hold rows already, with no default, so the same column is the
same everywhere. A passkey with none is read in the form passkeys were
first kept in. A project whose migrations predate the column takes one
migration adding it when jadpo check asks (migration.out_of_date).
Markdown for agents: /docs/system-tables.md.Built from Jadpo main at aee2e8f.