Skip to main content
A telemetry dataspace stores history: one row per sample, never updated in place. Use it for sensor streams, device datapoints, traces, counters, and any reading you will graph or aggregate later. The API modality is timeseries. Edge configs and conversation often say telemetry or append; those map to this modality. You cannot PUT or DELETE a sample through row CRUD. There is no current-row identity — only (source_id, event_ts). All modalities

When to use it

Use telemetry when
  • The row is a reading, not a record a UI will edit.
  • You have (or will freeze) a named column set: temperature, humidity, line_voltage.
  • Dashboards, rollups, and time-range scans matter.
  • The device is the only writer. A late sample is another point, not a conflict.
Use point instead when each sample is a sparse bag of metric names that changes per firmware or device, and you do not want to declare columns. Use state or mutable instead when the row must be updated or deleted.

Backing store

Telemetry lives in ClickHouse as a MergeTree (or ReplicatedMergeTree in clustered deployments). You never name the engine on create. Reads go through a read view that projects typed columns and, while the layout still has overflow, JSON paths from the overflow blob. Query the dataspace name (QueryScript) or the catalog read_view (raw SQL). Do not hardcode physical hot/cold table names.

Meta columns

Every telemetry row carries: User fields sit after these. version and is_deleted are not telemetry columns.

Schema and layouts

Default layout is jsonb: undeclared fields land in an overflow JSON blob and stay readable. As a path is observed at a stable type, you can promote it to a real column (hybrid, then typed). Promotion is how telemetry reaches a cheap cold tier: you cannot age a still-evolving jsonb / hybrid schema to immutable Parquet. If you request tiering: hot_cold at create while the layout is still evolving, the platform keeps the dataspace hot and records the request. Age-out turns on only after every field is typed and overflow is drained. Pass fields at create if you already know the column list. That is the honest way to start closer to typed. A project-wide cap of 1000 columns applies. Over-cap or type-mismatch rows on a typed layout go to the orphan table for review — they are not discarded.

Time window and late data

The write plane accepts a row when event_ts is not more than one day in the future. Future-dated rows go to dropped-rows (retained, with reason future). Late history (older than the hot window) is diverted only when the dataspace is hot_cold. That protects the immutable cold range. A hot-only telemetry dataspace accepts arbitrarily old backfill. Edge devices that buffer offline should stay untiered (hot) unless you explicitly accept dropped late batches.

Tiering and storage class

Cold data is immutable. You cannot rewrite a sample that has aged out. That is why evolving overflow layouts cannot tier.

Events and APIs

Telemetry does not emit a platform event per insert. Subscribe to derived signals or query the dataspace. There is no GET/PUT/PATCH/DELETE …/rows surface. List and filter history with QueryScript or POST /projects/{project_id}/dataspaces/query. Edge sync is upsync only. You cannot attach an edge_sqlite sync target to a telemetry dataspace (rejected). Devices send samples; the cloud does not push telemetry rows back.

Create

With known fields and a future cold tier (stays hot until promotion finishes):