Time Series
Lux has built-in time series support with retention policies, aggregation functions, label-based filtering, and cross-series queries. There are no modules to load or extensions to install. Time series data is stored natively and benefits from the same persistence, replication, and sharding as every other Lux data type.
TSADD
Append a sample to a time series. If the series does not exist, it is created automatically. Use * as the timestamp
to let Lux assign the current server time in milliseconds.
TSADD key timestamp value [RETENTION milliseconds] [LABELS label value [label value ...]]The RETENTION option
sets the maximum age of samples in milliseconds. Samples older than this are automatically pruned. The LABELS option attaches
key-value pairs to the series, which can be used for cross-series filtering with TSMRANGE.
127.0.0.1:6379> TSADD cpu:host1 * 72.5 RETENTION 86400000 LABELS host host1 region us-east
(integer) 1711036800000
127.0.0.1:6379> TSADD cpu:host1 * 68.3
(integer) 1711036801000
127.0.0.1:6379> TSADD cpu:host2 * 45.1 LABELS host host2 region eu-west
(integer) 1711036800500TSGET
Get the latest sample from a time series. Returns the timestamp and value of the most recent data point.
TSGET key127.0.0.1:6379> TSGET cpu:host1
1) (integer) 1711036801000
2) "68.3"TSRANGE
Query a range of samples between two timestamps. Use - and + as shorthand
for the earliest and latest timestamps in the series. The AGGREGATION option
downsamples results into fixed-size time buckets.
TSRANGE key from to [AGGREGATION type bucketSize]Supported aggregation types:
| Type | Description |
|---|---|
avg | Mean value per bucket |
sum | Sum of values per bucket |
min | Minimum value per bucket |
max | Maximum value per bucket |
count | Number of samples per bucket |
first | First value in the bucket |
last | Last value in the bucket |
range | Difference between max and min per bucket |
std.p | Population standard deviation |
std.s | Sample standard deviation |
var.p | Population variance |
var.s | Sample variance |
127.0.0.1:6379> TSRANGE cpu:host1 - + AGGREGATION avg 60000
1) 1) (integer) 1711036800000
2) "70.4"
2) 1) (integer) 1711036860000
2) "65.2"
127.0.0.1:6379> TSRANGE cpu:host1 1711036800000 1711036900000
1) 1) (integer) 1711036800000
2) "72.5"
2) 1) (integer) 1711036801000
2) "68.3"TSMRANGE
Query across multiple time series using label-based filters. This is how you ask questions like
"give me the average CPU across all hosts in us-east for the last hour." The FILTER option
matches against the labels you set with TSADD.
TSMRANGE from to [AGGREGATION type bucketSize] FILTER label=value [label=value ...]127.0.0.1:6379> TSMRANGE - + AGGREGATION avg 60000 FILTER region=us-east
1) 1) "cpu:host1"
2) 1) 1) (integer) 1711036800000
2) "70.4"TSMADD
Batch insert samples across multiple series in a single command. Each triplet is a key, timestamp, and value. This is significantly faster than issuing individual TSADD commands when you have many series to update at once.
TSMADD key1 timestamp1 value1 [key2 timestamp2 value2 ...]127.0.0.1:6379> TSMADD cpu:host1 * 72.5 cpu:host2 * 45.1 mem:host1 * 8192
1) (integer) 1711036800000
2) (integer) 1711036800000
3) (integer) 1711036800000TSINFO
Retrieve metadata about a time series, including the total number of samples, the first and last timestamps, the retention policy, and any attached labels.
127.0.0.1:6379> TSINFO cpu:host1
1) totalSamples
2) (integer) 1482
3) firstTimestamp
4) (integer) 1711036800000
5) lastTimestamp
6) (integer) 1711123199000
7) retentionTime
8) (integer) 86400000
9) labels
10) 1) 1) "host"
2) "host1"
2) 1) "region"
2) "us-east"Performance
TSGET runs at up to 18 million operations per second on a single instance. Write throughput with TSMADD scales linearly with batch size, making Lux suitable for high-frequency ingestion workloads.
SDK Example
The TypeScript SDK provides typed methods for all time series operations.
import Lux from "@luxdb/sdk";
const lux = new Lux("lux://127.0.0.1:6379");
await lux.tsadd("cpu:host1", "*", 72.5, {"'{'"}
retention: 86400000,
labels: {"'{'"} host: "host1", region: "us-east" {"'}'"},
{"'}'"});
const latest = await lux.tsget("cpu:host1");
// {"'{'"} timestamp: 1711036800000, value: 72.5 {"'}'"}
const range = await lux.tsrange("cpu:host1", "-", "+", {"'{'"}
aggregation: {"'{'"} type: "avg", bucketSize: 60000 {"'}'"},
{"'}'"});
// [{"'{'"} timestamp: 1711036800000, value: 70.4 {"'}'"}, ...]