Skip to content
Explainer · Time-series fundamentals

What Is a Time-Series Database? Architecture and Use Cases

A time-series database stores measurements that arrive in time order, such as a chiller's power draw every minute or a zone CO2 reading every 30 seconds, and is organised so that recent data is written quickly and ranges of time are read, aggregated and deleted cheaply. This article explains the data model, the write and read patterns, the architecture from sensor to dashboard, where the database sits next to message brokers and analytics platforms, typical building and IoT use cases, and when an ordinary relational database is the better choice.

Facts checked 27 October 2026 against the vendors' official documentation. Versions covered: PostgreSQL 18, TimescaleDB (Tiger Data documentation), InfluxDB 3 Core and InfluxDB OSS v2, QuestDB, Prometheus, MongoDB time series collections. Next review due April 2027. Products, licences and prices in this field change quickly; confirm on the vendor's site before you choose. No benchmarks are quoted unless the source and test setup are named.
Short answer
  • A time-series database is a database whose storage, indexing and housekeeping assume that every row is a timestamped measurement belonging to a series, and that most queries ask for a time range.
  • A series is identified by what was measured (a metric or point) plus descriptive labels such as site, asset and unit; each row adds one timestamp and one or more values.
  • Writes are append-mostly and continuous; reads are mostly "the last value", "this range" or "this range rolled up into buckets"; old data is removed by age, usually a whole time partition at a time.
  • The database is one stage of a pipeline: devices and gateways produce readings, a broker such as MQTT or a streaming platform such as Kafka moves them, the database stores and serves them, and a warehouse or lakehouse handles long-range analytics.
  • Our editorial view: plain PostgreSQL with declarative partitioning is often enough for building-scale data, and a specialised engine is worth evaluating when volume, retention or query load outgrow it in your own tests.
How we know: Research-based from the official documentation of PostgreSQL, TimescaleDB (Tiger Data), InfluxDB, QuestDB, Prometheus, MongoDB, Apache Kafka and MQTT, checked 27 October 2026. The two plain PostgreSQL queries on this page were run on PostgreSQL 18.6 (PGlite 0.5.11); no product-specific syntax is shown here, and no performance figures are quoted. Statements marked as our editorial view are judgements, not vendor statements or measurements. Volumes, intervals and windows used as examples (such as a few hundred points every 15 minutes or a three-day rule) are illustrative assumptions, not thresholds from any documentation.

What a time-series database is, and who this is for

Time-series data is a sequence of measurements in time order: the supply-air temperature of an air handling unit (AHU) sampled every minute, the kW reading of a chiller, a zone CO2 sensor, a half-hourly electricity meter. MongoDB's documentation puts it simply: insights come from analysing changes over time. Each new reading is appended; earlier readings are rarely changed.

A time-series database is a database built around that shape. Its storage is split by time, its indexes assume queries filter on a time range, it can usually compress long runs of similar values, and it has a cheap way to delete data once it passes a retention age. Some are separate products (InfluxDB, QuestDB, Prometheus's local storage); others are features added to a general database (TimescaleDB hypertables in PostgreSQL, MongoDB time series collections), and plain PostgreSQL can do a good part of the job with declarative partitioning.

This guide is for developers, data engineers and facilities or BMS engineers who need to store sensor and meter readings and want to understand the moving parts before choosing a product. The product guides and comparisons linked at the end go deeper.

The data model: series, timestamps, values and labels

Every time-series system has the same three ingredients, under different names:

  • Series identity: what was measured and where. Prometheus identifies every series by a metric name plus key-value labels; InfluxDB v2 combines a measurement name with a tag set into a series key; MongoDB keeps it in a metaField; in a relational design it is a point_id that references an asset and point table.
  • Timestamp: when the value was measured (not when it reached the database; the two differ for buffered or late data).
  • Values: one or more numbers, booleans or short strings. InfluxDB calls them fields, MongoDB metrics.

The distinction between identity and values matters for performance. InfluxDB v2 indexes tags but not fields, so filtering on a tag is cheap and filtering on a field value scans. Labels that take many distinct values (a reading ID, a user ID) create a new series per value, which is the "high cardinality" problem covered in the performance article.

Two layouts are common in SQL. A narrow table has one row per point per timestamp (point_id, ts, value) and suits BMS data where each point has its own interval. A wide table has one row per device per timestamp with a column per measurement, which suits devices that report a fixed set of values together. The storage guide uses the narrow layout.

The same concepts in different systems (terms from each vendor's documentation)
SystemSeries identityValuesTime partition unit
PostgreSQL (plain)Key columns such as point_id, joined to metadata tablesOrdinary columnsDeclarative partition (you create them)
TimescaleDBOrdinary columnsOrdinary columnsChunk of a hypertable (created automatically)
InfluxDB v2Measurement + tag set (series key)FieldsData kept in a bucket that has a retention period
PrometheusMetric name + labelsOne float sample per timestampTwo-hour blocks, compacted later
QuestDBColumns (often SYMBOL type)ColumnsPartition directory per time interval
MongoDBmetaFieldMeasurement fieldsInternal buckets

Write and read patterns

Writes arrive continuously from many sources, mostly in time order, often in batches from a gateway or consumer. Updates are rare (a corrected meter reading, a late quality flag) and deletes happen by age. Late and out-of-order readings are normal: a gateway that lost its uplink sends an hour of buffered values when it reconnects.

Reads fall into a few shapes: the latest value per point for a live dashboard; the raw values for one point over a range for a trend chart; values rolled up into time buckets (average, minimum, maximum per 15 minutes or per hour) for reports; and comparisons across many points over the same window for analytics. Almost every query has a time-range predicate.

Both of the common read shapes can be written in standard PostgreSQL. The queries below ran on PostgreSQL 18.6 against a small sample table (three sensors, one reading per minute for two hours).

PostgreSQL: latest value per sensor and hourly roll-up (run on PostgreSQL 18.6)
CREATE TABLE sensor_reading (
    sensor_id  integer NOT NULL,
    ts         timestamptz NOT NULL,
    value      double precision NOT NULL,
    PRIMARY KEY (sensor_id, ts)
);

-- Latest value per sensor (live dashboard tile)
SELECT DISTINCT ON (sensor_id) sensor_id, ts, value
FROM sensor_reading
ORDER BY sensor_id, ts DESC;

-- Hourly average, minimum and maximum (report)
SELECT sensor_id,
       date_bin(interval '1 hour', ts, timestamptz '2000-01-01 00:00+00') AS hour,
       round(avg(value)::numeric, 2) AS avg_value,
       min(value) AS min_value,
       max(value) AS max_value
FROM sensor_reading
WHERE ts >= '2026-10-27 08:00+00' AND ts < '2026-10-27 10:00+00'
GROUP BY 1, 2
ORDER BY 1, 2;
First rows of the hourly roll-up on the sample data
 sensor_id |          hour          | avg_value | min_value | max_value
-----------+------------------------+-----------+-----------+-----------
         1 | 2026-10-27 08:00:00+00 |     23.95 |        21 |      26.9
         1 | 2026-10-27 09:00:00+00 |     23.95 |        21 |      26.9
         2 | 2026-10-27 08:00:00+00 |     24.95 |        22 |      27.9

Time-series database architecture and data flow

A time-series database is rarely the first thing a reading touches. In a building or industrial site the path usually looks like this:

  1. Devices and controllers: sensors, meters and controllers on field protocols such as BACnet or Modbus.
  2. Edge gateway: polls or subscribes to the devices, normalises names and units, records when it collected each reading (and keeps the source's own event time where the device supplies one), buffers them when the uplink is down and publishes them upstream.
  3. Transport: an MQTT broker, a streaming platform such as Apache Kafka, or a direct HTTP write API.
  4. Ingestion: a consumer or connector that validates readings, maps them to point IDs, batches them and writes them to the database.
  5. Time-series storage: the database that keeps raw and rolled-up data and answers dashboard, alarm and report queries.
  6. Analytics: a warehouse or lakehouse that takes periodic extracts for long-range analysis and machine learning, joined with business data.

Keep the roles apart. MQTT is a lightweight publish/subscribe protocol designed for remote devices with little bandwidth: it moves messages, it does not answer "average CO2 on floor 3 last week". Kafka stores streams of events durably in partitioned, replicated topics and lets many consumers read them independently, which in our view makes it a useful buffer and fan-out point between producers and stores, but its retention is a log, not a query engine. The time-series database is where readings become queryable by point and time. A warehouse or lakehouse is where years of history meet work orders, energy tariffs and occupancy data for analysis.

Inside the database

Most engines share a handful of internal ideas, though the details differ:

  • Time partitioning. Data is split into pieces by time: TimescaleDB hypertables split into chunks covering a configurable range such as a day or a week; QuestDB stores each time interval in its own directory; Prometheus groups samples into two-hour blocks that are compacted later; PostgreSQL offers declarative range partitions. Queries skip pieces outside the requested range, and old pieces can be dropped whole.
  • Write-ahead log and in-memory head. Recent data is held in memory or a row-oriented area and protected by a log. Prometheus keeps the current block in memory, secured by a write-ahead log; TimescaleDB's hypercore writes new data to a rowstore and converts it to a columnstore later.
  • Columnar, compressed storage for older data, so that scanning one column across many rows reads fewer bytes.
  • Retention and downsampling: rules that drop or roll up data once it passes an age.

These features are the subject of the articles on compression and columnar storage and on retention and downsampling, and of the performance article linked below.

Time-series database examples

The products below are described from their own documentation; the last column is our editorial view, not a vendor statement or a measured result. Licences, editions and cloud offers change often; the selection guide and product articles keep the details.

Common time-series databases and how they are built
ProductWhat it isQuery languageTypical fit (our editorial view)
TimescaleDBPostgreSQL extension; hypertables partition data by time automatically, with a hybrid row and column storeSQL (PostgreSQL)Teams already on PostgreSQL who want time-series features with joins to relational data
InfluxDB 3 CorePurpose-built database for event and time series data; Parquet file persistence and object storage supportSQL and InfluxQLMonitoring, telemetry and dashboards that need recent data quickly
QuestDBTime-series database storing each column as a separate file, with a designated timestamp and time partitionsSQL with time-series extensionsHigh-rate ingestion with SQL queries
PrometheusMonitoring system with a local time series databasePromQLInfrastructure and application metrics scraped from targets
MongoDB time series collectionsA collection type in MongoDB that stores measurements from the same source togetherMongoDB query API and aggregationApplications already on MongoDB
PostgreSQL (plain)General relational database; declarative range partitioning by timeSQLBuilding-scale data with strong relational links

Use cases in BMS, CAFM, CMMS and IoT

Building management systems (BMS). A BMS exposes thousands of points: AHU supply and return temperatures, valve positions, fan speeds, chiller kW, zone temperature and CO2. Trend logs inside BMS controllers are often short; a time-series store keeps months or years of history for fault finding, commissioning checks and energy reports.

Energy and metering. Main and sub-meters report kWh, water and gas consumption at intervals set by the meter, the utility or the BMS, from seconds to an hour or more; check what your meters and contracts actually provide. Queries compare consumption by building, tenant, hour of day and season.

CAFM and CMMS. Computer-aided facility management and maintenance systems hold assets, locations, contracts and work orders: relational, transactional data that belongs in a relational database. The time-series store adds condition data to it. A rule such as "raise a work order when a chiller's average kW per tonne stays above its baseline for three days" (the three days is an illustrative window; choose it from how quickly the fault matters and how noisy the signal is) reads from the time-series store and writes a work order to the CMMS. Run-hour meters derived from status points feed planned maintenance intervals.

Industrial and general IoT. Machine telemetry, environmental sensors, vehicle and asset trackers: many devices, small messages, continuous arrival, frequent "last known value" lookups.

In all of these, the asset register stays relational. The time-series data references it by a stable point or asset ID, so that a renamed BMS point or a replaced sensor does not break history.

When a plain relational database is enough

A single PostgreSQL server with a narrow readings table, range partitions by month or day, a primary key on (point_id, ts) and a rolled-up table for reports covers, in our view, a great deal of building data. Dropping a partition removes a month of data far faster than a DELETE, and partition pruning keeps time-range queries to the partitions they need. The PostgreSQL documentation suggests partitioning becomes worthwhile when a table would otherwise be very large, with a rule of thumb that the table exceeds the server's physical memory.

Plain PostgreSQL is worth trying first when volumes are modest (as an illustrative scale, readings per minute or slower for thousands rather than millions of points; the real limit depends on your hardware, queries and retention, so test with your own data), when you need joins to asset, space and work-order tables in the same query, and when your team already runs PostgreSQL. The storage guide shows the full design with SQL that was run.

Signals that a specialised engine or extension is worth evaluating: sub-second or one-second sampling across many points, years of raw retention, storage cost dominated by readings, heavy aggregate queries over long ranges, or a need for automatic partition management and compression that you would otherwise build yourself.

When not to use a time-series database

  • Transactional records. Work orders, invoices, bookings and asset registers need constraints, updates and transactions on individual rows. Keep them in a relational database, even if they carry timestamps.
  • Small volumes. At an illustrative few hundred points every 15 minutes, the table stays small (about 28,800 rows a day for 300 points) and an ordinary relational database usually copes. Another engine adds operations work (backups, upgrades, monitoring, security) for little gain.
  • Heavy relational joins. If most queries join readings with many business tables, a time-series engine without full SQL joins pushes that work into application code or a warehouse.
  • Long-range analytics across the business. Year-on-year analysis joined with finance and occupancy data is usually better served by a warehouse or lakehouse fed from the time-series store.
  • Message transport. A database is not a message bus. Use MQTT or Kafka to move and buffer readings, not polling against a table.

Security, retention and operational considerations

  • Time. Store timestamps in UTC with a time-zone-aware type (timestamptz in PostgreSQL), keep device and gateway clocks synchronised, and record whether a timestamp is the measurement time or the arrival time.
  • Retention. Decide raw and rolled-up retention per data class before go-live; it drives storage size more than anything else.
  • Durability. Know what your engine replicates. Prometheus documents that its local storage is not clustered or replicated and should be managed like any single-node database.
  • Security. Authenticate and encrypt every hop (device to gateway to broker to database), give ingestion accounts write-only access to the tables they need, and keep BMS networks segmented from office and internet traffic.
  • Monitoring. Track ingestion lag, rejected or duplicate readings, partition creation and disk usage. A missing future partition or a full disk stops ingestion.

Where to go next

Start with How to Store IoT Sensor Data in a Database for a complete PostgreSQL design with partitioning, roll-ups, retention and a storage estimate. Time-Series Database Performance explains what drives ingest and query speed. For products, read the TimescaleDB, InfluxDB and QuestDB articles, the TimescaleDB vs InfluxDB and TimescaleDB vs PostgreSQL comparisons, and the guide to choosing a time-series database.

All time-series and IoT data articles

Time-series fundamentals

Time-series databases

Analytics and distributed databases

Cloud platforms

Streaming and messaging

Time-series data engineering

IoT data pipelines

Database operations

Anomaly detection

Frequently asked questions

What is a time-series database in simple terms?

A database designed for timestamped measurements that keep arriving, such as sensor readings or metrics. It stores data split by time, makes "show me this period" queries cheap, and can delete or roll up old data efficiently.

Is PostgreSQL a time-series database?

Not by design, but in our view it can handle time-series data at moderate scale with declarative range partitioning, suitable indexes and roll-up tables; test with your own data. TimescaleDB is a PostgreSQL extension that adds automatic time partitioning (hypertables), columnar compression and other time-series features.

What are examples of time-series databases?

TimescaleDB, InfluxDB, QuestDB and the local storage in Prometheus are common examples; MongoDB offers time series collections, and Apache IoTDB, TDengine and VictoriaMetrics are other options. Which fits depends on your query language, scale, retention and operations needs.

Do I need Kafka or MQTT if I have a time-series database?

They solve different problems. MQTT carries messages from constrained devices; Kafka buffers and fans out event streams durably to several consumers. The database stores and queries the readings. Small systems can write straight from a gateway to the database; larger ones usually put a broker or stream in between.

Where should CMMS work orders live?

In the CMMS's relational database. Use the time-series store to detect conditions (high runtime, drifting temperatures) and create or enrich work orders through the CMMS, referencing assets by a shared ID.

Sources

Checked 27 October 2026.

How we research these articles: our editorial method. Research-based from official documentation; SQL examples are run on a local database where the page says so. CodeWithSQL earns nothing from the vendors mentioned.

Building a sensor or telemetry database?

Start with the overview, or compare time-series databases side by side.