Time-series data
Time-series data (metrics, events, sensor readings) has a defining
shape: append-heavy, time-ordered, immense volume, and value that
decays with age. A general-purpose table handles it badly; the
techniques are all about exploiting the time dimension for storage,
retention, and query.
Method
- Partition by time. Range-partition on the timestamp
(daily or hourly by volume: see data-partitioning): so
queries filtering by time range prune to a few
partitions, and old data drops by detaching a partition
(near-instant) instead of deleting billions of rows.
Time partitioning is the foundational move that makes
everything else efficient.
- Downsample and expire by age. Recent data at full
resolution (per-second), older data aggregated
(per-minute, then per-hour), oldest expired entirely:
because nobody queries last year at second resolution.
Automated retention policies (roll up then drop raw)
keep storage bounded and queries fast (see
data-retention's tiering, sensor-data-handling for the
edge side). This aggregate-then-drop is the standard
time-series lifecycle.
- Exploit compression. Time-series compresses
extremely well (timestamps are near-regular, values
change slowly: delta and delta-of-delta encoding, plus
columnar storage): purpose-built stores achieve 10x+
ratios. Use the store's native compression; storing
time-series uncompressed in a general table wastes an
order of magnitude of disk.
- Handle out-of-order and late data. Readings arrive
late (network delays, batched device uploads: see
iot-messaging, sensor-data-handling); the store and
queries must accept writes into past windows and
recompute affected rollups (see incremental-processing's
late-data window). A design assuming strictly-increasing
timestamps breaks on the first delayed batch.
- Choose the right store for the scale. Purpose-built
time-series databases (Timescale, InfluxDB,
Prometheus-class) give partitioning, compression,
downsampling, and time-oriented query functions out of
the box; a relational table with manual partitioning
works at modest scale. Match the store to the volume and
query needs (see managed-vs-selfhosted): at high ingest
rates, the specialized store's built-in mechanics beat
hand-rolling them.
- Model for time-range queries and aggregation. The
dominant queries are "values over a time range,
aggregated by interval and grouped by series/tag":
design tags/dimensions for the group-bys you need (like
warehouse-modeling's grain, for time), index the time
plus tag columns (see indexing-strategy), and precompute
common rollups (continuous aggregates: see
materialized-views). Point lookups are rare;
range-scan-and-aggregate is the workload.
Boundaries
- Time-series stores optimize for append-heavy time-ordered
data; they are poor for data needing updates, complex
relations, or transactions (see transactions-isolation):
do not force relational workloads into them or vice
versa.
- Metrics/observability time-series (see
infrastructure-monitoring) and business/analytics
time-series overlap in technique but differ in tooling
and retention needs; match the stack to the use.
- Extremely high-cardinality tag combinations blow up many
time-series stores (each unique series is tracked);
cardinality management is the specific scaling gotcha to
design against.
1---2name: time-series-data3description: Store time-series data with retention downsampling, compression, out-of-order handling, and the right store choice. Use when handling metrics, events, or sensor streams that grow relentlessly by time.4---56# Time-series data78Time-series data (metrics, events, sensor readings) has a defining9shape: append-heavy, time-ordered, immense volume, and value that10decays with age. A general-purpose table handles it badly; the11techniques are all about exploiting the time dimension for storage,12retention, and query.1314## Method15161. **Partition by time.** Range-partition on the timestamp17 (daily or hourly by volume: see data-partitioning): so18 queries filtering by time range prune to a few19 partitions, and old data drops by detaching a partition20 (near-instant) instead of deleting billions of rows.21 Time partitioning is the foundational move that makes22 everything else efficient.232. **Downsample and expire by age.** Recent data at full24 resolution (per-second), older data aggregated25 (per-minute, then per-hour), oldest expired entirely:26 because nobody queries last year at second resolution.27 Automated retention policies (roll up then drop raw)28 keep storage bounded and queries fast (see29 data-retention's tiering, sensor-data-handling for the30 edge side). This aggregate-then-drop is the standard31 time-series lifecycle.323. **Exploit compression.** Time-series compresses33 extremely well (timestamps are near-regular, values34 change slowly: delta and delta-of-delta encoding, plus35 columnar storage): purpose-built stores achieve 10x+36 ratios. Use the store's native compression; storing37 time-series uncompressed in a general table wastes an38 order of magnitude of disk.394. **Handle out-of-order and late data.** Readings arrive40 late (network delays, batched device uploads: see41 iot-messaging, sensor-data-handling); the store and42 queries must accept writes into past windows and43 recompute affected rollups (see incremental-processing's44 late-data window). A design assuming strictly-increasing45 timestamps breaks on the first delayed batch.465. **Choose the right store for the scale.** Purpose-built47 time-series databases (Timescale, InfluxDB,48 Prometheus-class) give partitioning, compression,49 downsampling, and time-oriented query functions out of50 the box; a relational table with manual partitioning51 works at modest scale. Match the store to the volume and52 query needs (see managed-vs-selfhosted): at high ingest53 rates, the specialized store's built-in mechanics beat54 hand-rolling them.556. **Model for time-range queries and aggregation.** The56 dominant queries are "values over a time range,57 aggregated by interval and grouped by series/tag":58 design tags/dimensions for the group-bys you need (like59 warehouse-modeling's grain, for time), index the time60 plus tag columns (see indexing-strategy), and precompute61 common rollups (continuous aggregates: see62 materialized-views). Point lookups are rare;63 range-scan-and-aggregate is the workload.6465## Boundaries6667- Time-series stores optimize for append-heavy time-ordered68 data; they are poor for data needing updates, complex69 relations, or transactions (see transactions-isolation):70 do not force relational workloads into them or vice71 versa.72- Metrics/observability time-series (see73 infrastructure-monitoring) and business/analytics74 time-series overlap in technique but differ in tooling75 and retention needs; match the stack to the use.76- Extremely high-cardinality tag combinations blow up many77 time-series stores (each unique series is tracked);78 cardinality management is the specific scaling gotcha to79 design against.