Skip to main content
A dataspace has a schema independent of its modality and storage. Schema is layout (how columns sit in the engine) plus a catalog of fields (path, type, promotion state). You may pin layout and fields at create. If you omit them, the modality default applies and telemetry infers columns from traffic. Overview · Storage

Layouts (schema shape)

Layout is the physical column shape inside the engine. It is not the modality and not the storage class.
typed has no overflow. Use it only when you declare fields at create (or have finished promotion) and want undeclared columns rejected. A typed dataspace that still receives surprise keys orphans every such batch, with no automatic path to inventing the column.

Which layouts each modality allows

jsonb is the telemetry “start flexible” layout. map is the point “sparse KV” layout. Do not send map on telemetry or jsonb on mutable. Document and vector are the two modalities where the platform owns the column set: the upload and search surfaces read those columns by name, so fields you send at create are replaced rather than merged. The difference is what happens to anything else. A document dataspace is hybrid, so fields of your own — sent as metadata on a registration — are absorbed into overflow and read back. A vector dataspace is typed and has no overflow, because a search filter has to be a real indexed column.

Promotion ladder (telemetry)

Telemetry climbs as hot paths stabilize:
  1. jsonb — every user field in overflow. Fast to ingest; queries read JSON paths.
  2. hybrid — frequent, type-stable paths become real columns. The rest stays in overflow. The read view coalesces column with overflow.path so you do not see a seam.
  3. typed — overflow drained, schema frozen. Surprise keys orphan. This is the gate for tiering: hot_cold.
Point does not climb this ladder. State does not auto-promote (the inference job samples ClickHouse overflow only). Mutable can promote overflow → typed the same way as telemetry, but stays hot-only. Trigger promotion with PATCH /projects/{pid}/dataspaces/{id}/schema:
storage_class: cheap cannot promote — there is no hot MergeTree to ADD COLUMN and backfill. Freeze the schema before choosing cheap, or stay on fast.

Field catalog

Each user column is a field: a path (temperature, location.lat), a type, and a state.

Field types

Declare them in fields at create:
Hard cap: 1000 columns per dataspace. Over-cap rows go to orphan, and the caller sees an error.

Field state

On a typed layout there is no overflow state — a mismatch is an orphan, not a new overflow field. State hybrid overflow is queryable (the only modality where the overflow blob is a first-class read surface). ClickHouse overflow is exposed through the read view’s JSON/coalesce projection, not as a raw blob you select by default.

Dataspace schema state

The catalog also tracks a whole-dataspace schema_state: schema_version is monotonic. Every applied schema change bumps it. Producers and the write plane treat it as the generation of the catalog snapshot they normalized against.

Auto vs review

Attaching any edge sync target forces review. You do not want a mirrored SQLite table silently growing typed columns on the device’s cloud replica. List proposals: GET …/dataspaces/{id}/schema-proposals.

What happens to bad rows

Orphan is a schema problem. Late/future timestamps are a time-window problem and go to dropped-rows, not orphan.

Schema changes at runtime

Applying a schema change (promote, add typed column, freeze layout):
  1. Writes pause briefly for this dataspace (other dataspaces in the project wait in the durable buffer — no loss).
  2. Engine DDL runs (ALTER on Postgres or ClickHouse hot).
  3. Catalog fields, Arrow schema, and JSON schema regenerate; schema_version increments.
  4. Writes resume. Readers pick up the new schema on the next cache miss.
You cannot rename modality. You cannot jump typedjsonb. Promotion is forward. Natural-key columns should be declared in fields when you set natural_key, especially on state/mutable — those modalities do not invent columns from ClickHouse inference.