A standalone InfluxDB-style time-series engine, mounted like the SQL engine in the same process. Each series (measurement × tag-set × field) is a Gorilla-compressed columnar stream — about 0.3 bytes per point on regular data. Off by default; zero cost when unused.
OXIDB_TSDB=1 ./oxidb-server
# data under <OXIDB_DATA>/tsdb (override with OXIDB_TSDB_DATA)
TSDB requests carry "engine": "tsdb", "cmd": "tsdb", and an "op". Fields are typed (float / integer / boolean / string).
{ "engine": "tsdb", "cmd": "tsdb", "op": "write",
"measurement": "cpu", "tags": {"host": "a", "region": "eu"},
"fields": {"usage": 0.63}, "ts": 1700000000000 }
Ingest the InfluxDB line protocol verbatim — ms timestamps, now() when absent.
{ "engine": "tsdb", "cmd": "tsdb", "op": "write_lp",
"lp": "cpu,host=a,region=eu usage=0.63 1700000000000\ncpu,host=b usage=0.41" }
Filter by measurement, field, tags, and a [start, end) window; optionally downsample with GROUP BY time(interval) and group by tags.
{ "engine": "tsdb", "cmd": "tsdb", "op": "query",
"measurement": "cpu", "field": "usage",
"tag_filters": [{"key": "host", "value": "a"}],
"start": 1700000000000, "end": 1700003600000,
"interval": 600000, "group_by": ["region"],
"agg": "mean" }
| Agg | Meaning |
|---|---|
mean sum min max count first last distinct | Standard numeric aggregations |
rate | Per-second change (for counters) |
percentile (+ p), or p95 shorthand | Linear-interpolated percentile |
Text (string) fields support first / last / count / distinct.
Materialize completed time buckets of every numeric series into a derived measurement (<m>@<label>). Incremental via a crash-safe per-series watermark — no double-count on restart.
{ "engine": "tsdb", "cmd": "tsdb", "op": "rollup_add",
"measurement": "cpu", "interval": 60000, "aggs": ["mean", "max"] }
{ "engine": "tsdb", "cmd": "tsdb", "op": "rollup_refresh", "now": 1700003600000 }
// query the rollup as measurement "cpu@1m", field "usage_mean"
Retention drops whole expired blocks — durable for free. A checkpoint seals buffers, writes a fresh snapshot, and rotates the WAL (auto past 8 MiB).
{ "engine": "tsdb", "cmd": "tsdb", "op": "retention", "cutoff": 1699000000000 }
{ "engine": "tsdb", "cmd": "tsdb", "op": "checkpoint" }
{ "engine": "tsdb", "cmd": "tsdb", "op": "stats" }
Like the SQL engine, the TSDB has a consistent low-lock online backup — it pins a committed generation and compresses with the write lock released, so ingestion keeps flowing. Admin-only.
{ "engine": "tsdb", "cmd": "backup", "path": "/backups/tsdb.tar.gz" }
{ "engine": "tsdb", "cmd": "restore", "archive": "/backups/tsdb.tar.gz", "target": "/data/restored" }
A versioned block snapshot + per-generation WAL, with a MANIFEST as the atomic commit point. Every point is WAL-appended; a checkpoint writes a fresh snapshot, atomically replaces the MANIFEST, then rotates the WAL — a crash on either side never double-counts. Node-local. A Go client ships in the repo.