HTTP API

Endpoints, request bodies, responses, and data shapes exposed by Rad.

The Rad wire protocol: a small JSON over HTTP surface that clients and a Rad server speak to each other.

Errors use RFC 7807 Problem Details. Branch on the stable code field rather than parsing an error message.

Endpoints

Meta

Liveness and schema introspection.

MethodPathPurpose
GET/healthzCheck that the server is alive.
GET/infoDescribe this database.
GET/statisticsReturn the query-planner statistics this instance holds.
GET/tablesList the tables in the database.

GET /healthz

A cheap check that touches no storage. It always returns 200 with a small status body while the process is serving, so it is safe to use as a rad:// reachability test before opening a connection. It is database metadata, not an orchestrator signal: use /readyz and /livez for those.

Responses

StatusBodyMeaning
200application/json HealthThe server is alive.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /info

Return stable metadata for the database behind this endpoint. mode tells management tools whether catalog changes are available directly through the API or are owned by rad.schema.yaml migrations. schema_version identifies the latest committed catalog state, and schema_version_at reports when that version committed. location is the server's configured storage location and is intended for local development and administrative tooling.

Responses

StatusBodyMeaning
200application/json DatabaseInfoMetadata about the database behind this endpoint.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /statistics

Return the distilled model repository the planner estimates from: one entry per relation family, with observed row counts, estimate quality, execution latency, and the physical plans seen for it.

These are query-planner statistics, not operational metrics or tracing. They are advisory: deleting them changes no query result, and they are gathered best-effort, so a value may be missing after process failure or backpressure.

Several fields are deliberately approximate and named accordingly. A field ending UpperBound is a histogram bucket bound rather than an exact quantile, so it overstates; the matching exact maximum is reported beside it. Read the field descriptions before comparing numbers.

A process that runs no collector; a reader instance gathers statistics only for its own planner and a writer is the only publisher; returns 404 rather than an empty body, so "this instance does not collect" is distinguishable from "nothing observed yet".

Responses

StatusBodyMeaning
200application/json StatisticsThe planner statistics this instance currently holds.
404application/problem+json ProblemThe addressed resource, such as a transaction, does not exist.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /tables

Return every table currently defined in the catalog, along with its columns and primary key. This reflects the schema as it exists right now, after the most recent successful migration. An empty database returns an empty list, not an error.

Use this to introspect a running server without access to the original rad.schema.yaml file.

Responses

StatusBodyMeaning
200application/json TableListThe current set of tables.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

Probes

Process probes for orchestrators such as Kubernetes. They describe the serving process rather than the database's contents, never mutate catalog or application data, and are answerable before the database itself is available. An orchestrator decides from the HTTP status alone.

MethodPathPurpose
GET/livezReport whether the process and its critical tasks run.
GET/readyzReport whether the database can accept traffic.
GET/startupzReport whether the database finished starting.

GET /livez

Succeed while the process serves requests and every critical background task is alive. Storage never fails this probe: a temporary object-store or network outage must withdraw traffic through /readyz rather than restart a process that would come back to the same outage.

The reason is live, draining, or task_failed.

Responses

StatusBodyMeaning
200application/json ProbeStatusThe probed condition holds.
503application/json ProbeStatusThe probed condition does not hold.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /readyz

Succeed only while the process can serve the read or write access it was started with. It fails as soon as shutdown begins, as soon as the writer is fenced, and while storage is failing or has not been observed within the freshness window. A background task refreshes that observation, so answering the probe never issues a new object-store request.

The reason is starting, serving, draining, fenced, storage_unavailable, or storage_stale.

Responses

StatusBodyMeaning
200application/json ProbeStatusThe probed condition holds.
503application/json ProbeStatusThe probed condition does not hold.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /startupz

Succeed once storage is open, the catalog's identity and mode are validated, and the required background workers are running. Until then the process answers the probe endpoints and nothing else, so an orchestrator can bound initial storage startup without restarting a process that is still opening a slow object store, and no client reaches a partially initialized database.

A storage preflight monitors the object store while startup is held. The preflight sets the reason to show the cause of the hold. On success, the reason is started. While startup is held, the reason is starting, storage_bucket_missing, storage_unauthorized, or storage_unreachable.

Responses

StatusBodyMeaning
200application/json ProbeStatusThe probed condition holds.
503application/json ProbeStatusThe probed condition does not hold.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

Schema

Reconciling the database with a rad.schema.yaml file.

MethodPathPurpose
POST/schema/compatibilityVerify an exact generated-client schema identity.
POST/schema/diffPlan and preflight a desired schema without changing anything.
POST/schema/migrateStart or recover reconciliation with a desired schema.
GET/schemaReturn the current accepted schema.

POST /schema/compatibility

Verify an exact generated-client schema identity.

Request body

Content typeTypeRequiredDescription
application/jsonSchemaCompatibilityRequest

Responses

StatusBodyMeaning
204No bodyThe operation succeeded and there is no body to return.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

POST /schema/diff

This is an advisory point-in-time plan. The planner may account for matching durable work already in progress and omit a duplicate transition-start statement. Apply replans against current state and returns the authoritative transition identities accepted for the migration; diff does not return durable transition handles.

Request body

Content typeTypeRequiredDescription
application/jsonSchemaRequest

Responses

StatusBodyMeaning
200application/json SchemaDiffResultThe semantic diff, catalog PIR, and preflight findings.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

POST /schema/migrate

The server parses the desired schema, computes and preflights its semantic diff, and atomically commits immediate catalog work plus any durable online transition starts. The response is ready only when the current canonical schema equals desired_hash; otherwise it is converging and returns the transition identities to observe through the administrative API. Repeating the same desired-schema request recovers matching in-flight transitions instead of duplicating them. Destructive findings require accept_data_loss; blocking findings can never be bypassed.

Request body

Content typeTypeRequiredDescription
application/jsonSchemaMigrateRequest

Responses

StatusBodyMeaning
200application/json SchemaMigrateResultThe committed accepted schema and its identity.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /schema

Return the committed canonical schema together with its monotonic version and canonical hash.

Responses

StatusBodyMeaning
200application/json SchemaStateThe current accepted schema and identity.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

Administration

Inspecting and controlling durable database maintenance work.

MethodPathPurpose
POST/schema/transitions/{transition}/cancelCancel one durable online schema transition.
GET/schema/transitions/{transition}Inspect one durable online schema transition.
GET/schema/transitionsList durable online schema transitions.

POST /schema/transitions/{transition}/cancel

Atomically invalidate worker ownership, remove the transition's foreground write obligations, and schedule partial physical state for reclamation. Cancellation is idempotent for an already-cancelled transition. Ready and failed transitions reject cancellation because they require deletion or cleanup instead. This administrative transaction cannot be interleaved with application statements in a PIR program and is available in both catalog management modes.

Parameters

NameInTypeRequiredDescription
transitionpathstringYesThe durable transition identity returned when the work started.

Responses

StatusBodyMeaning
200application/json TransitionControlThe transition's durable administrative state.
403application/problem+json ProblemThe operation requires a write instance.
404application/problem+json ProblemThe addressed resource, such as a transaction, does not exist.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /schema/transitions/{transition}

Return the current durable identity and lifecycle state plus advisory progress and retained-work pressure. The observation is read from one coherent storage snapshot and does not claim or advance a worker.

Parameters

NameInTypeRequiredDescription
transitionpathstringYesThe durable transition identity returned when the work started.

Responses

StatusBodyMeaning
200application/json TransitionControlThe transition's durable administrative state.
404application/problem+json ProblemThe addressed resource, such as a transaction, does not exist.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

GET /schema/transitions

Return a coherent administrative snapshot of online schema work, including terminal transitions retained for diagnostics. Optional kind and state filters are applied to that snapshot. This endpoint never claims a worker or advances transition progress and is available in both direct and schema-managed catalog modes.

Parameters

NameInTypeRequiredDescription
kindqueryTransitionKindReturn only transitions using this physical protocol.
statequeryTransitionStateReturn only transitions in this durable lifecycle state.

Responses

StatusBodyMeaning
200application/json TransitionListA coherent snapshot of durable schema transitions.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

Catalog

Imperative catalog mutation: creating, updating, and deleting tables, columns, and indexes over the API. Available only on directly managed databases; a schema-managed database rejects every operation in this group with an invalid problem, since its catalog is owned by rad.schema.yaml migrations.

MethodPathPurpose
DELETE/tables/{table}/columns/{column}Delete a column.
PATCH/tables/{table}/columns/{column}Update a column.
POST/tables/{table}/columnsCreate a column on a table.
DELETE/tables/{table}/indexes/{index}Delete an index.
POST/tables/{table}/indexesCreate an index on a table.
DELETE/tables/{table}Delete a table.
PATCH/tables/{table}Update a table.
POST/tablesCreate a table.

DELETE /tables/{table}/columns/{column}

Remove a column. Stored values for it become unreachable. A column used by the primary key, an index, or a foreign key cannot be deleted; delete the index or foreign key holder first. On a schema-managed database this operation is always rejected.

Parameters

NameInTypeRequiredDescription
tablepathstringYesThe table's current name.
columnpathstringYesThe column's current name.

Responses

StatusBodyMeaning
200application/json TableInfoThe table's definition after the mutation was applied.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

PATCH /tables/{table}/columns/{column}

Update a column's properties. The only updatable property today is name; changing a column's type or nullability is not supported. A name change rewrites every metadata reference to the column (primary key, indexes, foreign keys), and rows are keyed by column ID, so no data is touched. On a schema-managed database this operation is always rejected.

Parameters

NameInTypeRequiredDescription
tablepathstringYesThe table's current name.
columnpathstringYesThe column's current name.

Request body

Content typeTypeRequiredDescription
application/jsonColumnUpdateProps

Responses

StatusBodyMeaning
200application/json TableInfoThe table's definition after the mutation was applied.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

POST /tables/{table}/columns

Append a column. Because existing rows have no value for it, the column must be nullable or carry a literal default. A nullable column may use a generator default; historical rows remain NULL while new creates run the generator. On a schema-managed database this operation is always rejected.

Parameters

NameInTypeRequiredDescription
tablepathstringYesThe table's current name.

Request body

Content typeTypeRequiredDescription
application/jsonColumnDef

Responses

StatusBodyMeaning
200application/json TableInfoThe table's definition after the mutation was applied.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

DELETE /tables/{table}/indexes/{index}

Remove an index from the catalog. Its entries become unreachable; index IDs are never reused. Queries that would have used it fall back to other access paths. On a schema-managed database this operation is always rejected.

Parameters

NameInTypeRequiredDescription
tablepathstringYesThe table's current name.
indexpathstringYesThe index's name.

Responses

StatusBodyMeaning
200application/json TableInfoThe table's definition after the mutation was applied.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

POST /tables/{table}/indexes

Register a secondary index and backfill entries for every existing row, atomically: the index never becomes visible without its entries. Backfilling a unique index over data that already contains duplicates fails with an invalid problem; retrying cannot succeed until the data changes; and the registration is rolled back with it. On a schema-managed database this operation is always rejected.

Parameters

NameInTypeRequiredDescription
tablepathstringYesThe table's current name.

Request body

Content typeTypeRequiredDescription
application/jsonIndexInfo

Responses

StatusBodyMeaning
200application/json TableInfoThe table's definition after the mutation was applied.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

DELETE /tables/{table}

Remove a table from the catalog. Its rows and index entries become unreachable; table IDs are never reused. A table that another table references through a foreign key cannot be deleted until the referencing table goes first (self-references do not count). On a schema-managed database this operation is always rejected.

Parameters

NameInTypeRequiredDescription
tablepathstringYesThe table's current name.

Responses

StatusBodyMeaning
204No bodyThe operation succeeded and there is no body to return.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

PATCH /tables/{table}

Update a table's properties. The only updatable property today is name: data keys use the table's ID, so a name change is metadata-only and instantaneous, and foreign keys referencing the table are unaffected. A name that is already taken is rejected with an invalid problem. On a schema-managed database this operation is always rejected.

Parameters

NameInTypeRequiredDescription
tablepathstringYesThe table's current name.

Request body

Content typeTypeRequiredDescription
application/jsonTableUpdateProps

Responses

StatusBodyMeaning
200application/json TableInfoThe table's definition after the mutation was applied.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

POST /tables

Define a new table in one call: columns, primary key, and optionally indexes and foreign keys, exactly as a rad.schema.yaml entry would. Stable schema IDs may be supplied or are assigned by the catalog, and the whole definition commits atomically; a rejected definition leaves nothing behind, including the name.

Foreign keys may reference existing tables or the table being created (self-references), and must target the referenced table's full primary key. A definition that fails validation; duplicate or missing name, unsupported column type, nullable primary key column, index or key over unknown columns; is rejected with an invalid problem. On a schema-managed database this operation is always rejected.

Request body

Content typeTypeRequiredDescription
application/jsonTableDef

Responses

StatusBodyMeaning
200application/json TableInfoThe table's definition after the mutation was applied.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

Data

Reading and writing rows against committed state.

MethodPathPurpose
OPTIONS/executeDescribe the operations available at the execute target.
POST/executeRun an execution program.
QUERY/executeRun one conditional LIR query.

OPTIONS /execute

Describe the operations available at the execute target.

Responses

StatusBodyMeaning
204No bodyThe execute target operations and QUERY request content type.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

POST /execute

Execute a program: an ordered list of named statements run as one atomic transaction. Each statement is a query, create, update, or delete over an LIR relation, and evaluates against the transaction's snapshot plus the effects of all preceding statements. A statement's result is available to later statements, by name, through an LIR ref; statement names share the binding namespace.

Mutations consume relations rather than literal rows: create inserts a relation's rows, update and delete identify target rows by the relation's primary-key columns. A literal row is simply a one-row rows relation.

Exactly one statement's result is returned, named by result (or the sole statement of a single-statement program). The response also carries a per-statement summary of affected row counts. If any statement fails validation or execution, or the commit loses a serializable race, the whole program fails and no effects become visible; a failed statement is named in the error.

The program envelope is validated before binding, and each statement's LIR relation against the independent LIR schema. Binding then resolves tables, columns, scopes, and statement references (which must point at earlier statements).

Parameters

NameInTypeRequiredDescription
show-planquerybooleanWhen true, the response carries the query plan for each statement - the physical plan and the planner's access-path decisions; as free-form JSON under plan, alongside the result (and on the problem when a statement fails after planning).
dry-runquerybooleanWhen true, bind and plan every statement but execute none: no writes, no result. With show-plan this returns the plan only; alone it is a "will this bind and plan?" validation that returns an empty success.

Request body

Content typeTypeRequiredDescription
application/jsonProgram

Responses

StatusBodyMeaning
200application/json ProgramResultThe result statement's datum plus a per-statement summary.
400application/problem+json ProblemThe request body was malformed or could not be decoded.
403application/problem+json ProblemThe operation requires a write instance.
409application/problem+json ProblemThe write lost an optimistic race; an immediate retry may win.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

QUERY /execute

Execute one LIR query against one committed snapshot. This operation cannot contain PIR statements or mutations. A successful response has a weak entity tag for the exact query and its complete dependency state. A matching If-None-Match returns 304 without executing the relation or serializing its result.

Parameters

NameInTypeRequiredDescription
If-None-MatchheaderstringEntity tags from an earlier response for this query target.

Request body

Content typeTypeRequiredDescription
application/vnd.rad.lir+jsonQueryYes

Responses

StatusBodyMeaning
200application/json ValueThe query result changed or no matching entity tag was supplied.
304No bodyThe supplied entity tag matches the current query representation.
400application/problem+json ProblemThe request body was malformed or could not be decoded.
406application/problem+json ProblemThe Accept header does not permit the query result representation.
413application/problem+json ProblemThe request body exceeds the server limit.
415application/problem+json ProblemThe request content type is not the LIR query media type.
422application/problem+json ProblemThe request was well formed but failed validation against the catalog.
500application/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.
defaultapplication/problem+json ProblemSomething went wrong inside the server that was not the caller's fault.

Data shapes

These reusable objects appear in request bodies, responses, and error details.

Access

Whether this process serves a checkpoint reader or owns the Slate writer.

ColumnDef

A column definition for a direct catalog create operation.

FieldTypeRequiredDescription
idintegerAn optional stable logical identity; direct mode allocates one when omitted. Format: int64.
namestringYes
typestringYesThe column's storage type, one of text, int64, float64, bool, or bytes.
nullableboolean
formatstringAn optional semantic hint such as uuid, ulid, xid, or unix_ms.
defaultColumnDefault

ColumnDefault

A column default, applied when an insert omits the column: either a builtin generator named by func (uuid_v4 or uuid_v7 on bytes format: uuid, ulid on bytes format: ulid, xid on bytes format: xid, and now_ms or increment on int64 columns) or a literal value of the column's type. Exactly one is set.

FieldTypeRequiredDescription
funcuuid_v4 | uuid_v7 | ulid | xid | now_ms | incrementA builtin generator.
valuevalueA literal of the column's type. Formatted byte columns use their canonical identifier text; unformatted bytes use padded base64.

ColumnInfo

One column of a table, as reported by introspection.

FieldTypeRequiredDescription
idintegerYesThe stable logical column identity within its table. Format: int64.
namestringYes
typestringYesThe column's storage type, one of text, int64, float64, bool, or bytes.
nullableboolean
formatstringAn optional semantic hint such as uuid, ulid, xid, or unix_ms.
defaultColumnDefault

ColumnUpdateProps

The column properties to update.

FieldTypeRequiredDescription
namestringYesThe column's new name.

ConflictContext

Schema-level identity for a raced object, when resolvable.

FieldTypeRequiredDescription
objectConflictObject
tablestring
indexstring
operationConflictOperation

ConflictObject

ConflictOperation

ConflictProblem

DatabaseInfo

Stable metadata about a Rad database.

FieldTypeRequiredDescription
accessAccessYes
modedirect | schemaYesThe database's catalog management mode: direct (the catalog is mutable over this API) or schema (rad.schema.yaml migrations own the catalog and the imperative catalog operations are rejected).
schema_versionintegerYesThe monotonic version of the committed schema. A fresh database starts at zero. Each catalog change in direct mode increments it once, including each reconciler step; an entire schema-managed migration increments it once. Format: int64.
schema_hashstringYesSHA-256 of the canonical committed schema JSON.
schema_version_atstringWhen the current schema version committed. Absent at version zero. Format: date-time.
locationstringThe configured backing-store location, when the server exposes one.

ExecutionContext

The physical execution identity available at failure.

FieldTypeRequiredDescription
operatorstringThe stable physical operator name used by EXPLAIN.
operator_idstring
tablestring
indexstring
bindingstring
crossingstring

ExecutionFailedProblem

ForeignKeyAction

The action applied to referencing rows when the referenced row is deleted.

ForeignKeyInfo

One foreign key, in both definitions and introspection. The referenced columns must be the referenced table's full primary key.

FieldTypeRequiredDescription
namestringYes
columnsarray of stringYesThe referencing column names on this table.
ref_tablestringYesThe referenced table's name.
ref_columnsarray of stringYesThe referenced table's primary key columns, in order.
on_deleteForeignKeyActionYes

Health

The liveness status of the server.

FieldTypeRequiredDescription
statusstringYes
accessAccessYes
modestringYesThe database's catalog management mode: direct (the catalog is mutable over this API) or schema (rad.schema.yaml migrations own the catalog and the imperative catalog operations are rejected).

IndexInfo

One secondary index, in both definitions and introspection.

FieldTypeRequiredDescription
namestringYes
columnsarray of stringYesThe indexed column names, in order.
uniqueboolean

InternalProblem

A database failure that prevents the operation from completing. The detail contains the complete available diagnostic, including wrapped causes. incident correlates the response with the server log.

InvalidDiagnostic

One diagnostic within a multi-error invalid problem.

FieldTypeRequiredDescription
reasonstringYes
detailstringYes
locationProblemLocation

InvalidProblem

NotFoundProblem

ProbeStatus

Why a probe answered as it did. The HTTP status is the answer; this body is a diagnostic for whoever is reading curl output or a failing test, and orchestrators ignore it.

FieldTypeRequiredDescription
reasonstringYesA stable token naming the process state behind the result. Each probe reports its own set, listed in that operation's description.

Problem

An RFC 7807 Problem Details object. Every non-2xx response carries one. code is the stable top-level discriminator; reason is the fine-grained semantic identity within that class.

Variants: InvalidProblem, ExecutionFailedProblem, NotFoundProblem, ConflictProblem, InternalProblem

ProblemBase

FieldTypeRequiredDescription
typestringYesA stable class-level URN such as urn:rad:problem:conflict.
titlestringYesA short human-readable summary of the problem class.
statusintegerYesThe HTTP status code, repeated in the body for convenience.
detailstringA human readable explanation specific to this occurrence.
reasonstringYesThe stable fine-grained identity within the problem class. Reasons accumulate over time; generated clients must preserve unknown strings and fall back to code rather than rejecting a response.

ProblemLocation

Identifies the request construct associated with the problem. JSON Pointer is machine-navigable; the other fields are semantic labels. Fields are omitted when that provenance is unavailable. Table, index, column, binding, and node names may appear; key bytes and row values never do.

FieldTypeRequiredDescription
pointerstringAn RFC 6901 JSON Pointer into the submitted document.
nodestringThe LIR node identifier associated with the problem.
bindingstringThe binding name associated with the problem.
scopestringThe relation scope associated with the problem.
rolestringA display-oriented structural role such as predicate or order term 0.

ProblemStage

The engine stage that rejected or failed the operation.

Program

An arbitrary JSON object containing a PIR execution program. As with Query, the HTTP contract does not describe the PIR grammar; servers validate this raw body against the independent PIR JSON Schema, and each statement's relation against the LIR schema.

ProgramResult

The result of a program: the declared result statement's datum (shaped exactly as its LIR root materialises, as in QueryResult), plus a per-statement summary in execution order.

FieldTypeRequiredDescription
resultvalueYes
statementsarray of StatementResultYes
planvaluePresent only when the request set show-plan. Free-form JSON: the query plan for each statement; the physical plan and the planner's access-path decisions, plus a rendered text form. Transport observability metadata, not part of the LIR/PIR IR; its structure is deliberately unspecified here and evolves with the planner.

Query

An arbitrary JSON object containing one LIR query. The HTTP contract does not duplicate the LIR grammar. Servers validate this body against the independent LIR JSON Schema.

QueryResult

The result of a query: one datum, shaped exactly as the root materialises. A many root is an array of records; first is a record or null; exactly_one is a record; scalar is a naked value or null. Nested first fields are objects (or null) and nested array fields are arrays, recursively.

FieldTypeRequiredDescription
resultvalueYes

ResourceContext

The addressed API resource, without storage keys or row values.

FieldTypeRequiredDescription
kindstringYes
namestring

SchemaChange

FieldTypeRequiredDescription
kindstringYes
summarystringYes
tablestring
columnstring

SchemaCompatibilityRequest

FieldTypeRequiredDescription
schema_versionintegerYesFormat: int64.
schema_hashstringYes

SchemaDiffResult

An advisory point-in-time comparison with the desired schema. program is the work a newly accepted apply would currently need; it may omit a transition start when matching durable work is already in progress. Apply replans transactionally and returns its authoritative transition identities.

FieldTypeRequiredDescription
current_versionintegerYesFormat: int64.
current_hashstringYes
desired_hashstringYes
changesarray of SchemaChangeYes
programValueYes
destructivearray of SchemaFindingYes
blockingarray of SchemaFindingYes

SchemaDocument

The accepted canonical logical schema.

FieldTypeRequiredDescription
tablesarray of TableDefYes

SchemaFinding

FieldTypeRequiredDescription
kindstringYes
summarystringYes
tablestring
columnstring
rowsintegerFormat: int64.

SchemaMigrateRequest

A desired schema, the preflighted server identity, and explicit data-loss consent.

FieldTypeRequiredDescription
schemastringYes
current_versionintegerYesFormat: int64.
current_hashstringYes
accept_data_lossboolean

SchemaMigrateResult

SchemaRequest

A desired schema source to plan.

FieldTypeRequiredDescription
schemastringYesThe full rad.schema.yaml source document, as YAML.

SchemaState

FieldTypeRequiredDescription
schema_versionintegerYesFormat: int64.
schema_hashstringYes
schemaSchemaDocumentYes

StatementResult

One statement's lightweight outcome. Durable schema work additionally returns a typed control object; relational and immediate catalog statements omit it.

FieldTypeRequiredDescription
namestringYes
affectedintegerYesFor relational statements, the number of rows produced, created, updated, or deleted. A successful immediate catalog or transition start reports one affected object.
controlvalueYesA typed non-relational result. Transition-start controls contain kind: transition, durable identities, lifecycle state and generation, retained-work health, advisory progress/lag, and terminal diagnostics. Worker ownership epochs and physical storage positions are internal and are not exposed. Statements without a control result emit JSON null. This namespace is not a LIR relation and cannot be referenced by a PIR ref.

Statistics

FieldTypeRequiredDescription
absorbedintegerYesObservations folded into the models since this process started. Format: int64.
droppedintegerYesObservations discarded because the collection queue was full. Execution never blocks to record statistics, so a busy instance sheds observations rather than slowing queries. Format: int64.
evictedintegerYesModels discarded to keep the working set bounded. The frequency sketch keeps counting an evicted family, so a family that stays active is re-admitted. Format: int64.
shedintegerYesUnpublished evidence discarded to keep the pending set bounded. Evidence already published is unaffected: what reaches the store accumulates there. Format: int64.
corpusStatisticsCorpusYes
relayStatisticsRelayYes
trackedFamiliesintegerYesRelation families currently modelled.
modelsarray of StatisticsModelYesOne entry per modelled family, most measured first.
synopsesarray of StatisticsSynopsisYesCurrent table survey results, ordered by table identity.
physicalCostStatisticsPhysicalCost

StatisticsColumnGroupSynopsis

FieldTypeRequiredDescription
columnsarray of integerYesStable column schema identities in canonical order.
valueGenerationsarray of integerYesColumn value generations in the same order as columns.
nullCountintegerYesObserved rows where one or more group columns contained null. Format: int64.
distinctintegerYesExact or approximate observed distinct non-null value combinations. Format: int64.
distinctIsExactbooleanYesWhether distinct is exact.
mostCommonValuesarray of StatisticsMostCommonColumnGroupYesBounded common value combinations, ordered by decreasing observed frequency.

StatisticsColumnSynopsis

FieldTypeRequiredDescription
columnintegerYesStable column schema identity. Format: int64.
valueGenerationintegerYesColumn value generation that this synopsis describes. Format: int64.
nullFractionnumberYesFraction of observed rows that contained null. Format: double.
nullCountintegerYesObserved rows that contained null. Format: int64.
distinctintegerYesExact or approximate observed distinct non-null values. Format: int64.
distinctIsExactbooleanYesWhether distinct is exact.
averageWidthintegerYesAverage encoded width of observed non-null values. Format: int64.
minimumstringRendered minimum non-null value.
maximumstringRendered maximum non-null value.
mostCommonValuesarray of StatisticsMostCommonValueYesBounded heavy hitters, ordered by decreasing observed frequency.

StatisticsCorpus

FieldTypeRequiredDescription
enabledbooleanYesWhether this process captures canonical workload programs.
capturedintegerYesPrograms admitted to the local statistics queue. Format: int64.
skippedOversizeintegerYesPrograms not captured because one canonical document exceeded the capture limit. Format: int64.
droppedQueueintegerYesPrograms not captured because the collection queue was full. Format: int64.
shedPendingintegerYesCaptured programs removed from the bounded unpublished queue. Format: int64.
maintenancevalueStorage maintenance data. This field is absent when this process does not own corpus storage.

StatisticsCorpusMaintenance

Cumulative maintenance counters and current retained corpus gauges. Counters start when the storage owner process starts.

FieldTypeRequiredDescription
expiredExecutionsintegerYesExecution records removed because the maximum age elapsed. Format: int64.
prunedExecutionsintegerYesExecution records removed to enforce the count or byte limit. Format: int64.
invalidExecutionsintegerYesExecution records removed because their key, value, or program reference was invalid. Format: int64.
prunedProgramsintegerYesCanonical programs removed because no retained execution referenced them. Format: int64.
invalidProgramsintegerYesCanonical programs removed because their storage key was invalid. Format: int64.
erasedExecutionsintegerYesExecution records removed by explicit corpus erasure. Format: int64.
erasedProgramsintegerYesCanonical programs removed by explicit corpus erasure. Format: int64.
retainedExecutionsintegerYesExecution records currently retained. Format: int64.
retainedProgramsintegerYesUnique canonical programs currently retained. Format: int64.
retainedProgramBytesintegerYesBytes in retained canonical programs. This excludes execution records and storage overhead. Format: int64.

StatisticsModel

FieldTypeRequiredDescription
kindstringYesrelation contains logical relation cardinality feedback. statement contains complete statement performance and plan data.
familystringYesFamily fingerprint: the relation shape with every literal replaced by a typed placeholder, so the same shape run with different parameters shares one entry. Carries the canonicalization version and hash algorithm that produced it.
exactVariantsintegerYesApproximate distinct literal-specific instances seen within this family. A fixed-size mergeable sketch produces this value. One means an effectively constant query. A large value means a parameterised query. Format: int64.
frequencyintegerYesApproximate number of times this family appeared anywhere in an executed query tree, from a count-min sketch. It over-counts on hash collision and halves periodically, so it reflects recent workload weight rather than a lifetime total. Expect it to exceed retainedExecutions: a family is counted once per appearance as a subtree but measured only where a plan boundary exposes its rows. Format: int64.
retainedExecutionsintegerYesTimes this family was itself measured. Format: int64.
executionsWithEstimateintegerYesOf those, how many carried a planner estimate to score against the actual row count. Zero means nothing has scored this family yet. Format: int64.
rowsP50UpperBoundintegerYesUpper bound on the median row count: the bound of the histogram bucket holding it, never above rowsMax. Not an exact quantile. Format: int64.
rowsP95UpperBoundintegerYesUpper bound on the 95th-percentile row count. Format: int64.
rowsMaxintegerYesLargest row count observed, exactly. Format: int64.
qErrorP50UpperBoundnumberYesUpper bound on the median estimate error, symmetric and multiplicative: 1.0 is a perfect estimate and 10.0 is wrong by a factor of ten in either direction. A bucket bound, never above qErrorMax.
qErrorP95UpperBoundnumberYesUpper bound on the 95th-percentile estimate error.
qErrorMaxnumberYesLargest estimate error observed, exactly.
executeMicrosP50UpperBoundintegerUpper bound on median execution time in microseconds. Absent when this family was measured only as a relation inside a statement, which records rows but not durations. Format: int64.
executeMicrosP95UpperBoundintegerUpper bound on 95th-percentile execution time in microseconds. Format: int64.
durationEwmaMicrosintegerExponentially weighted mean execution time, a recent-trend signal rather than a distribution. Absent alongside the latency bounds. Format: int64.
plansarray of StatisticsPlanYesPhysical plans observed for this family, with how often each ran.
planningValueStatisticsPlanningValue
resourceCostStatisticsResourceCost

StatisticsMostCommonColumnGroup

FieldTypeRequiredDescription
valuesarray of stringYesRendered typed values in the column order.
frequencyintegerYesSpace-Saving frequency upper bound. Format: int64.
lowerFrequencyintegerYesGuaranteed observed frequency lower bound. Format: int64.
maximumErrorintegerYesMaximum Space-Saving overcount. Format: int64.

StatisticsMostCommonValue

FieldTypeRequiredDescription
valuestringYesRendered typed value.
frequencyintegerYesSpace-Saving frequency upper bound. Format: int64.
lowerFrequencyintegerYesGuaranteed observed frequency lower bound. Format: int64.
maximumErrorintegerYesMaximum Space-Saving overcount. Format: int64.

StatisticsPhysicalCacheCost

FieldTypeRequiredDescription
tiermemory | localYes
accessesintegerYesFormat: int64.
hitsintegerYesFormat: int64.
hitRatePpmintegerYesFormat: int64.

StatisticsPhysicalCost

Instance-local physical storage calibration. Backend adapters convert their native metrics to this common model. A missing capability is false and its measurements are absent. The model is not assigned to one statement or relation.

FieldTypeRequiredDescription
basisbackend_physical_telemetryYes
backendstringYes
telemetryFormatintegerYesFormat: int64.
capabilitiesStatisticsPhysicalTelemetryCapabilitiesYes
requestsarray of StatisticsPhysicalRequestCostYes
cachesarray of StatisticsPhysicalCacheCostYes

StatisticsPhysicalCostMetric

FieldTypeRequiredDescription
p50UpperBoundintegerYesUpper bound on the median value. Format: int64.
p95UpperBoundintegerYesUpper bound on the 95th-percentile value. Format: int64.
maximumUpperBoundintegerYesUpper bound on the largest value in the retained buckets. Format: int64.

StatisticsPhysicalRequestCost

FieldTypeRequiredDescription
classread | range_read | metadata_read | write | delete | listYes
observedRequestsintegerYesFormat: int64.
errorsintegerYesFormat: int64.
latencyMicrosStatisticsPhysicalCostMetric
bytesStatisticsPhysicalCostMetric
sizeUpperBoundintegerRequest-size bucket upper bound for this conditional model. Format: int64.
concurrencyUpperBoundintegerActive-request bucket upper bound for this conditional model. Format: int64.
serviceTiermemory | local | remoteService tier for this conditional model.

StatisticsPhysicalTelemetryCapabilities

FieldTypeRequiredDescription
requestLatencybooleanYes
requestBytesbooleanYes
requestConcurrencybooleanYes
cacheTiersbooleanYes
accessLocalitybooleanYes

StatisticsPlan

FieldTypeRequiredDescription
planstringYesStructural fingerprint of the physical plan: operator shapes, access paths, join order, and binding strategies, excluding literal values.
executionsintegerYesTimes this plan ran for this family. Format: int64.

StatisticsPlanningValue

Observational priority proxy. It is present only when at least two plans have enough execution evidence in the same access generation and row-count class. It does not claim that an estimate caused a plan change. A future counterfactual optimizer can replace the observed A counterfactual optimizer replaces the observed plan-variation component without changing the other components.

FieldTypeRequiredDescription
scoreintegerYesFrequency multiplied by normalized uncertainty, observed plan variation, and the median execution-time difference. The two normalized components use parts per million. Format: int64.
frequencyintegerYesRecent workload frequency used by the score. Format: int64.
uncertaintyPpmintegerYesNormalized p95 q-error excess in parts per million. Format: int64.
observedPlanVariationPpmintegerYesNon-dominant comparable plan executions in parts per million. Format: int64.
costDifferenceMicrosintegerYesDifference between the fastest and slowest comparable median execution times. Format: int64.
comparableExecutionsintegerYesExecutions represented by the comparable plan group. Format: int64.
rowCountClassUpperBoundintegerYesMedian row-count histogram bound shared by the plan group. Format: int64.
minimumExecutionsintegerYesMinimum estimates and per-plan executions required for admission. Format: int64.
basisstringYesStable identifier for the score method.

StatisticsRelay

The observation relay, as this instance sees it. An instance that cannot publish to storage hands its evidence to one that can; the channel is advisory, so every loss here is counted rather than signalled as a failure.

The sending fields are absent on an instance that publishes to storage rather than to a peer. The receiving fields are always present, because every instance can receive; zero means nothing has arrived.

FieldTypeRequiredDescription
stateconnected | retrying | losing | idleThe sending side in one word. retrying means a batch is held for another attempt and no evidence has been lost yet. losing means a batch was abandoned or refused, so evidence was dropped, and it stays reported until a later attempt succeeds. Absent on an instance that does not send.
sentintegerBatches this instance successfully handed to a peer. Format: int64.
abandonedintegerBatches given up on after exhausting their retry budget. Each one is evidence permanently lost, which costs the fleet planner accuracy and nothing else. Format: int64.
rejectedintegerBatches a peer understood and refused, most often a wire-format mismatch during a rolling upgrade. Retrying cannot help, so these are not retried. Format: int64.
holdingbooleanWhether a batch is currently awaiting another attempt.
corpusSentintegerWorkload-corpus documents carried to a peer. These contain the literal values of the programs that ran, unlike the aggregate evidence beside them, so they travel only over a transport shown to be confidential; encrypted and verified. Format: int64.
corpusWithheldintegerCorpus documents dropped because the transport could not be shown confidential. An instance that cannot publish has nowhere else to put them. A non-zero value with corpus capture requested means the channel is not encrypted. Format: int64.
receivedintegerYesBatches accepted from a peer and queued to be merged. Format: int64.
receivedAlreadyAppliedintegerYesBatches whose sequence this instance had already applied. Delivery is at-least-once and the accounting is idempotent, so a repeat is expected traffic rather than a fault. Format: int64.
receivedRejectedintegerYesBatches refused because they use a different wire format. Format: int64.
receivedSaturatedintegerYesBatches refused because the merge queue was full. The sender is asked to retry and nothing is recorded as applied, so a saturated receiver costs latency rather than evidence. Format: int64.
receivedCorpusOversizeintegerYesBatches refused because one corpus document exceeded 1 MiB. Format: int64.
sourcesintegerYesPeers whose applied sequence this instance remembers. A peer that falls out of that bounded set is re-admitted on its next batch. Format: int64.
mergedObservationsintegerYesObservations folded in from peers. Format: int64.
corpusAdoptedintegerYesCorpus documents adopted from peers. Content addressing makes a duplicate harmless, so this counts documents received rather than documents newly stored. Format: int64.
refusedStaleFamiliesintegerYesRelayed families discarded because they described a different catalog generation than this instance observed. A peer lagging a catalog change must never displace newer local evidence. Format: int64.

StatisticsResourceCost

Observed logical KV work for complete statement executions. This is not CPU, memory, object-request, or remote-I/O cost. A relation model has no resource cost because shared statement work cannot be assigned to one relation without an operator measurement boundary.

FieldTypeRequiredDescription
basislogical_kv_workYes
observedExecutionsintegerYesComplete statement executions in these distributions. Format: int64.
getsStatisticsResourceMetricYes
putsStatisticsResourceMetricYes
deletesStatisticsResourceMetricYes
scansStatisticsResourceMetricYes
iteratedStatisticsResourceMetricYes
bytesReadStatisticsResourceMetricYes
bytesWrittenStatisticsResourceMetricYes

StatisticsResourceMetric

FieldTypeRequiredDescription
p50UpperBoundintegerYesUpper bound on the median value. Format: int64.
p95UpperBoundintegerYesUpper bound on the 95th-percentile value. Format: int64.
maximumintegerYesLargest observed value, exactly. Format: int64.

StatisticsSynopsis

FieldTypeRequiredDescription
tableintegerYesStable table schema identity. Format: int64.
observedRowsintegerYesRows read by the survey. Format: int64.
coveragecomplete | prefixLimitYesWhether the survey read the complete table or a bounded prefix.
sampleSizeintegerYesRows used to build the synopsis. Format: int64.
changesSinceCollectionintegerYesRows affected by writes after collection. Format: int64.
tableExistenceGenerationintegerYesTable generation that this synopsis describes. Format: int64.
collectedAtUnixMicrosintegerYesCollection wall time in microseconds since the Unix epoch. Format: int64.
catalogVersionintegerYesCatalog version read by the survey. Format: int64.
columnsarray of StatisticsColumnSynopsisYes
columnGroupsarray of StatisticsColumnGroupSynopsisYesBounded joint statistics for primary-key prefixes, ready multi-column index prefixes, and composite foreign keys.

TableDef

A new table's definition, mirroring a rad.schema.yaml entry as JSON. The direct API may omit logical IDs for the catalog to allocate. Column types are text, int64, float64, bool, or bytes; the primary key is required and its columns must not be nullable.

FieldTypeRequiredDescription
idintegerAn optional stable logical identity; direct mode allocates one when omitted. Format: int64.
namestringYes
columnsarray of ColumnDefYes
primary_keyarray of stringYes
indexesarray of IndexInfo
foreign_keysarray of ForeignKeyInfo

TableInfo

One table's definition, as reported by introspection.

FieldTypeRequiredDescription
idintegerYesThe stable logical table identity within this database. Format: int64.
namestringYes
columnsarray of ColumnInfoYes
primary_keyarray of stringYesThe column names that make up the primary key, in order.
indexesarray of IndexInfo
foreign_keysarray of ForeignKeyInfo

TableList

The set of tables defined in the database.

FieldTypeRequiredDescription
tablesarray of TableInfoYes

TableUpdateProps

The table properties to update.

FieldTypeRequiredDescription
namestringYesThe table's new name.

TransitionControl

The administrative projection of a durable schema transition. Identity, protocol kind, lifecycle state, generation, prerequisite edges, and terminal diagnostics are normative. Progress and retained-work values are advisory snapshots. Worker epochs and physical storage positions remain internal.

FieldTypeRequiredDescription
kindtransitionYes
transition_idstringYes
object_idstringYesStable logical identity of the index, column, or constraint being produced.
transition_kindTransitionKindYes
stateTransitionStateYes
generationintegerYesFormat: int64.
prerequisitesarray of stringYesDurable transition identities that must publish ready before this transition can activate.
retained_work_stateTransitionWorkStateYes
last_errorstringTerminal or most recent worker diagnostic, when present.
rows_scannedintegerYesFormat: int64.
applied_deltaintegerYesFormat: int64.
delta_lagintegerYesFormat: int64.

TransitionKind

The physical protocol used to perform online schema work.

TransitionList

A coherent administrative snapshot of durable schema transitions.

FieldTypeRequiredDescription
transitionsarray of TransitionControlYes

TransitionState

The durable lifecycle state of online schema work.

TransitionWorkState

Advisory retained-work pressure. write_gated means affected writes are temporarily rejected until the worker catches up or terminates.

Value

An arbitrary JSON value carried by the HTTP protocol.