Skip to main content
Version: 1.0.4

Historian

The historian stores tag values over time and answers trend queries. It runs as its own service and writes to a QuestDB store.

The path a value takes

A device reading passes through the protocol worker to the historian, which writes to the historian store, buffers while the store is unreachable, keeps a live tail of recent samples, and serves charts from the store, the rollup or the tail.A device reading passes through the protocol worker to the historian, which writes to the historian store, buffers while the store is unreachable, keeps a live tail of recent samples, and serves charts from the store, the rollup or the tail.
Charts read the rollup for long ranges and the live tail for the last few minutes.
  1. Scaling and deadband are applied at the edge, so stored values are in engineering units and noise never reaches storage.
  2. The historian stores only tags with history enabled.
  3. Writes go through the store-and-forward buffer — an unreachable QuestDB buffers and replays in order rather than losing data.
  4. A 1-minute rollup materialises aggregates for long-range queries.
  5. A live tail buffer holds the most recent samples in memory and merges them into live chart queries, closing the sub-second window between ingestion and QuestDB's flush.

Enabling history

Per tag: set Enable history, and optionally a store interval and a deadband.

PropertyEffect
Enable historyStream this tag to the historian
DeadbandSuppress changes smaller than this — the biggest lever on volume
Store interval (ms)Force a point at this interval even without change, proving the signal was alive

Tag properties

One designated store

Exactly one QuestDB connection is the system historian, named by a single system setting rather than a per-connection flag — so "two historians" cannot be represented at all.

Only that connection (plus any still holding historised tags) is provisioned with a historian table, a rollup, WAL settings, an ingestion worker and a retention sweep. A QuestDB connection added purely as a data source is left alone.

Historian configuration

History epochs

Changing the historian would ordinarily truncate every chart at the switchover: a "last 30 days" query issued against the new store returns only the days since the change, with no sign the rest exists.

QUBIQ records an epoch instead: connection X was the historian from t1 to t2. A read resolves its window to the overlapping epochs, queries each one's store, and stitches the timeline back together.

Two consequences worth knowing:

  • Migrating the historian is non-destructive. Trends span the change.
  • Retiring a store means retiring its epoch, not deleting history you still want to read.

Range statistics are recombined exactly across epochs — min/max are extremal, counts and sums additive, and averages and standard deviations are reconstructed from the (Σx², Σx, n) trio rather than being averaged, which would be wrong whenever epochs hold different sample counts.

Store ownership

Two QUBIQ installations writing to one QuestDB historian table is silent corruption. An application-level check cannot see another machine, so QUBIQ records physical ownership inside the store itself.

A store owned by a different installation — a cloned VM, a restored backup, a decommissioned instance — is refused, with an ownership banner. Claiming it is a deliberate, audited action.

QuestDB

Self-healing

Three mechanisms keep history flowing without operator action:

MechanismHandles
Schema-drift detectionQuestDB auto-creating a table with the wrong designated timestamp, which would silence every read. Detected, alarmed, and repairable by rebuild.
WAL supervisionTables suspended by a failed write-ahead-log apply. Recoverable stalls resume automatically; poison segments are alarmed rather than looped on.
Rollup rebuildA stale or incorrect 1-minute aggregate, rebuilt on demand.

Automatic repair declines above a size threshold, so a configuration change cannot trigger a minutes-long re-aggregation unannounced at boot. The operator-triggered rebuild is the deliberate counterpart.

Querying

FromHow
A screenHistorian or HmiTrendChart widget
A scriptsystem.hist.getTrends(paths, start, end, maxPoints, agg)
A pipelineThe Python node, via system.hist

Always bound the result. A day of one-second data is 86,400 points per tag; the server aggregates to your maxPoints target so the browser receives something it can actually draw.

Querying history

Retention

A sweep runs daily and drops whole partitions past the configured age. Partition drops are metadata operations in QuestDB, so retention is nearly free — which is why day-granular partitioning is the sensible default.

Set deadbands before you set retention. Not storing a row is far cheaper than storing and later deleting it.

What the historian is not

  • Not a general data warehouse. It stores tag time-series. Batch records, orders and documents belong in SQL or MongoDB.
  • Not the audit journal. Security events go to a separate external database, deliberately outside QUBIQ's control. → Audit journal
  • Not a backup. History is not included in a configuration backup; QuestDB is backed up by your normal database procedures.

In this section

PageContents
ConfigurationDesignating the store, tuning ingestion, retention
Querying historyTrends, aggregation, statistics and performance