ApiaryActive
Try: pause · settings · learn · wipe
← Community / Reading Room
TD
databases · 13 min read

Time‑Series Databases Fundamentals

In the past decade the market for TSDBs has exploded: InfluxDB reported 1 billion data points per month in 2023, Prometheus powers monitoring for 80 % of the…

Time‑series data is the heartbeat of modern monitoring, scientific research, and automated decision‑making. From a beehive’s temperature sensor reporting a reading every second to an AI‑driven fleet of drones streaming telemetry at 10 kHz, the ability to store, query, and act on chronologically ordered measurements is what turns raw numbers into insight. This article pulls back the curtain on the technology that makes that possible—time‑series databases (TSDBs). We’ll explore how data gets in, how it’s kept alive (or deliberately retired), how we compress and downsample it, and the query languages that let us extract meaning at scale. Along the way we’ll sprinkle concrete numbers, real‑world examples, and occasional bridges to bee conservation and self‑governing AI agents, because the same principles that keep a server farm humming also help a hive thrive.

In the past decade the market for TSDBs has exploded: InfluxDB reported > 1 billion data points per month in 2023, Prometheus powers monitoring for > 80 % of the top‑500 cloud‑native workloads, and specialized systems such as TimescaleDB have become the default for financial tick data handling > 100 million rows per second. Yet many developers still treat a TSDB as a “fancy key‑value store” and miss the nuanced design choices that affect cost, latency, and reliability. Understanding those choices is essential whether you are building a bee‑health dashboard that aggregates hive weight, humidity, and acoustic signatures, or designing an AI‑agent platform that must react to millions of events per second without choking on historic data.

Below you’ll find a deep dive into the core concepts that underpin any production‑grade TSDB. The sections are deliberately self‑contained, so you can jump to the parts that matter most for your project, but reading the whole article will give you a holistic view of how ingestion, retention, downsampling, and query intersect to form a resilient data pipeline.


1. What Is a Time‑Series Database?

A time‑series database is a purpose‑built storage engine optimized for data that is:

CharacteristicWhy It Matters
Immutable, append‑onlyNew measurements are added with a timestamp; existing points are rarely updated, allowing sequential writes and high throughput.
Ordered by timeIndexes can be simplified to a single dimension (the timestamp), which dramatically speeds range scans.
High cardinalityEach series can be uniquely identified by a set of tags (e.g., location=apiary-7, sensor=temperature). Systems must handle millions of distinct series without performance collapse.
Retention‑drivenOlder data is often less granular, so the engine must support automated expiration or roll‑up.

Unlike relational databases that store rows in arbitrary order, TSDBs treat the timestamp as a first‑class citizen. This leads to design patterns that differ in three key areas:

  1. Write Path – Bulk ingestion pipelines that can sustain 10 k–1 M points per second per node (e.g., InfluxDB’s line protocol can ingest ~1.2 M points/s on a single 8‑core VM with SSD storage).
  2. Storage Engine – Columnar or hybrid storage that compresses repeated tag values and exploits the monotonic nature of timestamps.
  3. Query Model – Time‑range predicates are native; aggregations like avg() over 5m are first‑class operations.

Because the data model is simple, TSDBs can be schema‑light: you define measurement names and tags on the fly, and the engine automatically creates the necessary metadata. This flexibility is why they have become the default for IoT, observability, and scientific telemetry.

Bridge to bees: A modern beehive monitoring system may generate 5–10 measurements per second per hive (temperature, humidity, weight, sound amplitude, CO₂). With 1 000 hives, that’s ~10 M points per day—a perfect workload for a TSDB that can store raw data for 30 days and downsample to hourly averages for long‑term trend analysis.

2. Data Ingestion Pipelines – From Sensors to Storage

2.1 Protocols and Formats

Most TSDBs accept data over line‑protocol (plain‑text key/value), JSON, or gRPC. The choice influences latency and bandwidth:

ProtocolTypical Payload SizeLatency (ms)Use‑Case
InfluxDB line protocol~30 B per point1–2High‑frequency IoT
Prometheus remote write (protobuf)~50 B per point<1Cloud‑native monitoring
OpenTelemetry OTLP (gRPC)~100 B per point0.5–1Distributed tracing + metrics

Because timestamps are part of the payload, the client must synchronize clocks (via NTP or PTP). A drift of just 1 s can misplace a point in a bucketed aggregation, leading to inaccurate alerts.

2.2 Batching and Back‑Pressure

Writing each point individually creates a system call per point and kills throughput. Production pipelines therefore batch points:

# Example line protocol batch (10 points)
temperature,location=apiary-7,sensor=thermometer value=34.2 1695715200
temperature,location=apiary-7,sensor=thermometer value=34.1 1695715201
...

Most clients let you configure a batch size (e.g., 5 k points) and a flush interval (e.g., 100 ms). The trade‑off is latency vs. efficiency:

  • Large batch, high latency: Good for bulk import, not for real‑time alerts.
  • Small batch, low latency: Increases CPU usage and network overhead.

Back‑pressure mechanisms (e.g., HTTP 429 responses, gRPC flow control) prevent the TSDB from being overwhelmed. In a high‑throughput scenario—say, a fleet of 10 000 autonomous drones each sending 2 k telemetry points per second—the ingestion layer must be horizontally scalable. A typical pattern is a sharded HTTP reverse proxy (e.g., NGINX or Envoy) that routes points based on a hash of the series tags.

2.3 Data Validation and Enrichment

Before persisting, pipelines often:

  1. Validate the timestamp (must be within an acceptable skew, e.g., ±5 s).
  2. Normalize tag values (lowercase, replace spaces).
  3. Enrich with derived fields (e.g., compute temperature_f = value * 9/5 + 32).

These steps can be performed in a stream processing framework such as Apache Flink or Kafka Streams. The enriched stream then writes to the TSDB via a sink connector (e.g., flink-connector-influxdb). This approach keeps the ingestion path stateless, which is essential for scaling out.

Example: An apiary sensor network streams raw temperature readings to a Kafka topic. A Flink job validates timestamps, adds a day_of_year tag, and writes the enriched points to InfluxDB. The downstream query SELECT mean(value) FROM temperature WHERE time > now() - 1h GROUP BY time(5m), location now benefits from the extra tag for faster grouping.

3. The Storage Engine: Append‑Only Logs, Compression, and Indexing

3.1 Write‑Ahead Log (WAL) and Immutable Segments

Most TSDBs use an append‑only write‑ahead log (WAL) to guarantee durability. The flow is:

  1. Receive batch → write to WAL (sequential disk write, ~200 MB/s on a SATA SSD, >1 GB/s on NVMe).
  2. Memtable (in‑memory buffer) accumulates points until a size threshold (e.g., 64 MiB) is reached.
  3. Flush → immutable on‑disk segment (often called an “TSM file” in InfluxDB or “chunk” in TimescaleDB).

Because segments are immutable, compaction can happen offline without blocking writes. This design mirrors LSM‑tree databases (e.g., RocksDB) and enables high write throughput while maintaining strong durability.

3.2 Compression Techniques

Time‑series data is highly compressible due to:

  • Repeated tag values (e.g., location=apiary-7 appears in millions of points).
  • Monotonic timestamps (differences between successive timestamps are often small).
  • Similar metric values (temperature varies slowly).

Common compression schemes:

Data TypeAlgorithmTypical Ratio
Timestamps (delta‑of‑delta)Gorilla (Facebook)10–15:1
Float valuesGorilla XOR + bit‑packing4–8:1
Tags (dictionary)Run‑length + dictionary5–20:1
Integer countersVarint + delta3–6:1

For example, InfluxDB’s TSM engine reports a 12:1 compression on a dataset of 1 billion temperature points (average 8 bytes per raw point). TimescaleDB, built on PostgreSQL, can achieve 6:1 using columnar compression (timescaledb.compress_segmentby).

3.3 Indexing by Tags and Time

A TSDB must locate series quickly. The typical index structure is a two‑level map:

  1. Tag Set Index – a hash map from a canonical tag combination (e.g., location=apiary-7|sensor=temperature) to a series ID.
  2. Time Index – per‑series offset tables that point to the on‑disk segments covering a given time range.

This design yields O(1) series lookup and O(log N) segment location (where N is the number of segments per series). In practice, a query that filters on location='apiary-7' can resolve to < 10 ms even with 10 M series.

Performance tip: Keep the cardinality of tags low. Adding a high‑cardinality tag (e.g., a UUID per point) can explode the tag set index, turning a 10 ms lookup into seconds. For bee‑level data, use tags like hive_id, sensor_type, and avoid per‑reading unique identifiers.

4. Retention Policies and Lifecycle Management

4.1 Why Retention Matters

Raw telemetry is valuable for troubleshooting, but storing every point forever is rarely cost‑effective. A typical retention strategy looks like:

TierDurationResolutionStorage Cost
Hot30 daysRaw (1 s)High (SSD)
Warm1 year1 min averagesMedium (NVMe)
Cold∞1 hour averagesLow (HDD)

The retention policy (RP) automates the deletion of data that has outlived its usefulness. In InfluxDB, you define an RP per database:

CREATE RETENTION POLICY "30d" ON "apiary" DURATION 30d REPLICATION 2 SHARD DURATION 1d DEFAULT

A background purge task runs every shardDuration (e.g., daily) and removes entire shards that exceed the RP. This approach is shard‑aware, meaning that a single purge operation can delete gigabytes of data with minimal I/O.

4.2 Multi‑Tier Retention with Continuous Queries

Many TSDBs support continuous queries (CQs) or materialized views that automatically downsample data as it ages. Example in InfluxDB:

CREATE CONTINUOUS QUERY "cq_5m" ON "apiary"
BEGIN
  SELECT mean(value) AS avg_temp
  INTO "apiary"."30d"."temperature_5m"
  FROM "temperature"
  GROUP BY time(5m), location
END

The CQ reads raw points, computes a 5‑minute average, and writes the result into a downsampled measurement that lives under a different RP (e.g., 1 year). This pattern eliminates the need for an external ETL job.

4.3 Legal and Ethical Considerations

When dealing with environmental data—such as GPS locations of hives—privacy regulations (e.g., GDPR) may require data minimization. Retention policies can be used to automatically purge personally‑identifiable metadata after a defined period, ensuring compliance without manual intervention.


5. Downsampling, Roll‑ups, and Continuous Queries

5.1 The Need for Downsampling

Raw data at 1 s granularity can quickly become unwieldy. Consider a global bee‑health network with 50 k hives, each emitting 5 points per second:

50,000 hives × 5 points/s = 250,000 points/s
≈ 21.6 B points/day
≈ 7.9 TB raw per year (assuming 8 bytes per point)

Storing all of that at full resolution is expensive. Downsampling reduces the volume while preserving trends:

  • 5‑minute averages for long‑term climate analysis.
  • Hourly max/min for alert thresholds (e.g., temperature spikes).

5.2 Roll‑up Strategies

There are three main roll‑up strategies:

StrategyWhen to UseExample
Simple aggregationFixed time bucketsSELECT mean(value) FROM temperature GROUP BY time(5m)
Hierarchical roll‑upMulti‑tier retentionRaw → 5 m → 1 h → 1 d
Statistical sketchApproximate quantiles, heavy‑tailUse t-digest or DDSketch to store 99th‑percentile of hive sound amplitude.

Hierarchical roll‑ups are often implemented as cascading CQs: one CQ writes to a 5‑minute bucket measurement, a second CQ reads that measurement and writes to an hourly bucket, and so on.

5.3 Real‑Time vs. Near‑Real‑Time Downsampling

If you need sub‑second alerts, you cannot wait for a nightly batch job. Instead, you can:

  • Use a streaming processor (e.g., Flink) that computes rolling windows (TumblingEventTimeWindows.of(Time.minutes(5))) and writes directly to the TSDB.
  • Leverage native TSDB functions like Prometheus’ rate() which calculates per‑second increase over the last 5 minutes on the fly.

The trade‑off is resource consumption: real‑time roll‑ups increase CPU load on the TSDB nodes, while offline roll‑ups shift the load to a separate batch system.


6. Query Languages – From SQL‑Like to Domain‑Specific

6.1 InfluxQL & Flux (InfluxDB)

InfluxQL mimics classic SQL:

SELECT mean(value) AS avg_temp
FROM temperature
WHERE time > now() - 7d AND location='apiary-7'
GROUP BY time(1h) fill(null)

Flux (the newer functional language) adds:

  • First‑class functions (map, filter, aggregateWindow).
  • Cross‑bucket joins (e.g., correlating temperature and humidity).
  • User‑defined functions (UDFs) written in JavaScript or Go.

Example Flux query that computes a heat index:

from(bucket:"apiary")
  |> range(start: -30d)
  |> filter(fn: (r) => r._measurement == "temperature" or r._measurement == "humidity")
  |> pivot(rowKey:["_time"], columnKey: ["_measurement"], valueColumn: "_value")
  |> map(fn: (r) => ({
        _time: r._time,
        heat_index: 0.8 * r.temperature + r.humidity * 0.1
    }))
  |> aggregateWindow(every: 1h, fn: mean)

Flux’s pipeline model is well‑suited for AI agents that need to transform raw telemetry into features before feeding them into a model.

6.2 PromQL (Prometheus)

Prometheus uses PromQL, a selector‑based language:

avg_over_time(temperature{location="apiary-7"}[5m])

Key concepts:

  • Instant vectors (current values) vs. range vectors (values over a time window).
  • Functions (rate, increase, histogram_quantile) that operate on range vectors.
  • Label matching ({sensor=~"temp|humid"}) for flexible tag filtering.

PromQL’s fast in‑memory execution (data stored in a custom TSDB) makes it ideal for real‑time alerting. However, it lacks native joins, which can be a limitation when correlating multiple measurements.

6.3 SQL Extensions (TimescaleDB)

TimescaleDB extends PostgreSQL with time‑series capabilities:

SELECT time_bucket('5 minutes', time) AS bucket,
       avg(temperature) AS avg_temp
FROM measurements
WHERE hive_id = 42
GROUP BY bucket
ORDER BY bucket DESC;

Additional functions:

  • time_bucket_gapfill – fills missing intervals.
  • approximate_percentile – uses t‑digest.
  • hypertable – a partitioned table that automatically creates time‑based chunks.

Because it runs on PostgreSQL, you can join with relational tables (e.g., hive metadata, species taxonomy) using standard SQL, which is valuable for AI agents that need both telemetry and static knowledge.

6.4 Choosing the Right Language

Use‑CaseRecommended LanguageReason
High‑frequency alerting (sub‑second)PromQL (Prometheus)In‑memory, low latency
Complex feature engineering for AIFlux (InfluxDB) or SQL (TimescaleDB)Functional pipelines / joins
Multi‑tenant SaaS with strict ACIDTimescaleDB (PostgreSQL)Transactional guarantees
Edge devices with minimal footprintInfluxQL (line protocol)Simple, low overhead

7. Scaling Horizontally – Sharding, Replication, and Multi‑Tenant Isolation

7.1 Horizontal Sharding

When write throughput exceeds a single node’s capacity (≈ 1 M points/s on modern NVMe), you must shard data across multiple TSDB instances. Common strategies:

  1. Hash‑based sharding on tag set – e.g., hash(location) % N. Guarantees that all points from the same hive go to the same node, simplifying queries that need to aggregate per hive.
  2. Time‑range sharding – each node owns a slice of time (e.g., one month). Works well for immutable data but complicates real‑time queries that span shards.

Open‑source projects like Cortex (for Prometheus) and InfluxDB Enterprise provide a meta‑service that maps series to shards and routes queries automatically.

7.2 Replication for High Availability

Two replication models dominate:

ModelConsistencyWrite PathExample
Leader‑Follower (Raft)Strong (linearizable)Write to leader, replicate to followersInfluxDB Enterprise, TimescaleDB with synchronous replication
Quorum‑based (Gossip)Eventual (tunable)Write to any node, quorum ackPrometheus remote write to Cortex, VictoriaMetrics cluster

For AI agents that must react within 500 ms to a sensor anomaly, strong consistency is preferable to avoid split‑brain scenarios where one node thinks the anomaly exists while another does not.

7.3 Multi‑Tenant Isolation

A SaaS platform serving multiple apiaries needs to keep each tenant’s data isolated for security and billing. Techniques include:

  • Namespace per tenant (e.g., separate databases in InfluxDB).
  • Tag‑based tenant ID with row‑level security (supported in TimescaleDB via PostgreSQL RLS).
  • Physical isolation – dedicated nodes per tier (hot vs. cold) for cost control.

Isolation also helps with query planning: the optimizer can prune irrelevant shards early, reducing CPU load.


8. Real‑World Patterns: Monitoring, Environmental Science, and Bee Conservation

8.1 Cloud‑Native Monitoring (Prometheus + Cortex)

A typical stack:

  1. Exporters on each service expose /metrics in Prometheus format.
  2. Prometheus server scrapes at 15‑second intervals, writes to its local TSDB (≈ 100 M samples per day per server).
  3. Remote write streams data to Cortex, which shards by tenant and stores on object storage (e.g., S3) for long‑term retention.
  4. Grafana visualizes with PromQL queries.

Performance numbers from Cortex’s production run (2022):

  • 10 M active series.
  • 2 k queries/s average latency
Frequently asked
What is Time‑Series Databases Fundamentals about?
In the past decade the market for TSDBs has exploded: InfluxDB reported 1 billion data points per month in 2023, Prometheus powers monitoring for 80 % of the…
1. What Is a Time‑Series Database?
A time‑series database is a purpose‑built storage engine optimized for data that is:
What should you know about 2.1 Protocols and Formats?
Most TSDBs accept data over line‑protocol (plain‑text key/value), JSON , or gRPC . The choice influences latency and bandwidth:
What should you know about 2.2 Batching and Back‑Pressure?
Writing each point individually creates a system call per point and kills throughput. Production pipelines therefore batch points:
What should you know about 3.1 Write‑Ahead Log (WAL) and Immutable Segments?
Most TSDBs use an append‑only write‑ahead log (WAL) to guarantee durability. The flow is:
References & sources
  1. Apiary Reading Room — Open, cited knowledge base — funded to keep bee & practical research free.
From the Apiary Reading Room. Opinion & editorial — not financial advice. We don't overclaim.
More from the Reading Room