Q: Time-series databases — what makes them different?

Answer:

A time-series DB (TSDB) is optimized for append-only, timestamp-indexed data with high write volume and range-scan reads. Trying to do this in a normal RDBMS is a path to pain.

What Makes Data "Time-Series"

  • Each record has a timestamp.
  • New data is mostly appended at "now."
  • Updates are rare; deletes are bulk (retention).
  • Queries scan ranges by time: "last 5 min," "yesterday."
  • Aggregations dominate: rate, sum, p99 over windows.

Use cases: monitoring metrics, IoT sensor data, financial ticks, user activity events.

TSDBLineage
InfluxDBNative TSDB; popular for IoT
PrometheusPull-based monitoring
TimescaleDBPostgres extension; SQL+TSDB
Druid / PinotReal-time analytics columnar
ClickHouseColumnar OLAP, doubles as TSDB
OpenTSDB / KairosDBHBase-backed
VictoriaMetricsPrometheus-compatible, denser

Optimizations

Append-only writes: no random writes; sequential disk patterns; high throughput.

Compression: Gorilla algo (timestamps as delta-of-delta, values as XOR diff) → ~1.4 bytes/sample.

Time-partitioned storage: each chunk covers a time window; old chunks dropped wholesale.

Indexes by (series, timestamp): range queries find the chunk + scan.

Downsampling: roll up raw → 1-min → 5-min → 1-hour at increasing retention.

Schema: Series

series_id = hash(metric_name + label_set)
data = [(ts, value), (ts, value), ...]

A series is a unique combination of labels. Each new label combination creates a new series.

Cardinality = total unique series. Bad labels (user_id, request_id) explode cardinality → OOM.

Querying

Prometheus PromQL example:

sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)

InfluxDB Flux:

from(bucket: "metrics")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "cpu" and r.host == "h1")
  |> aggregateWindow(every: 1m, fn: mean)

TimescaleDB SQL:

SELECT time_bucket('1 minute', time) AS bucket, avg(value)
FROM cpu_usage
WHERE host = 'h1' AND time > now() - INTERVAL '1 hour'
GROUP BY bucket
ORDER BY bucket;

Retention

Time-based retention is built in:

keep raw for 7 days
keep 1-min downsampled for 30 days
keep 1-hour downsampled for 1 year

Dropping a time window = dropping a chunk file. Trivial.

vs Generic RDBMS

If you try Postgres for metrics at scale:

  • 100k inserts/sec hits write throughput.
  • Indexes bloat from constant inserts.
  • Vacuum overhead.
  • Time-range queries do sequential scan on huge tables.

TimescaleDB sidesteps this by chunking (auto-partitioning by time) on top of Postgres + columnar compression. Best of both: SQL + TSDB performance.

vs OLAP (ClickHouse, BigQuery)

OLAP DBs are great for time-series too. ClickHouse, Druid, Pinot:

  • Columnar storage.
  • Excellent aggregations.
  • Higher query latency than dedicated TSDBs but more flexible (joins, distinct counts).

For metrics: TSDB. For events with rich querying: OLAP. The line blurs.

Cardinality Management

Sources of explosion:

  • Per-user labels.
  • Per-request IDs.
  • Per-pod UUIDs in K8s.
  • Free-form text labels.

Rule of thumb:

  • Labels: < 10 values per label, < 10 labels.
  • Cardinality budget per metric: ~10,000 series.
  • High-cardinality goes to logs/events, not metrics.

Scale

Million-series TSDBs commonplace.
Tens-of-millions with sharded/clustered solutions.
Hundreds-of-millions: managed (Mimir, VictoriaMetrics cluster, M3DB).

Single node holds ~1M series, 100k samples/sec.

Multi-Tenant / Federated

For organization-wide metrics:

  • Per-team / per-cluster TSDB.
  • Federation: central queries fan out to clusters.
  • Or: managed multi-tenant (Cortex, Mimir, Datadog).

Common Mistakes

MistakeFix
Using RDBMS for high-volume time-seriesTSDB or OLAP
User ID as a labelCardinality death
Querying months at raw resolutionUse downsampled
Single global retentionPer-metric retention sized to value
Logging individual events as metricsUse logs/traces; metrics are aggregates

[!NOTE] Time-series databases trade flexibility for compression + write performance. They're not "a SQL database with a timestamp column" — they're a specialized engine and need to be treated as such.

Interview Follow-ups

  • "When would you NOT use a TSDB?" — Ad-hoc analytics with complex joins; rich relational queries — use a warehouse instead.
  • "How would you store both metrics and traces?" — Metrics in TSDB; traces in dedicated trace store (Tempo, Jaeger); logs in Loki/Elastic. Three pillars, three stores.
  • "What's downsampling, and what does it cost?" — Aggregate raw points into coarser buckets (1m → 5m → 1h) over time. Cost: small CPU to compute; you lose precision but save 12–60× storage.