11 min read
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
Time-Series DB (InfluxDB, TimescaleDB)
1. What Is It?
A time-series database (TSDB) is a database optimized for storing and querying data points indexed by time — metrics, events, sensor readings, and telemetry. The distinguishing characteristic is that timestamps are the primary dimension: data is always written with a timestamp and queried over time ranges, often with aggregations (avg, max, min, rate-of-change) across fixed time buckets.
Without time-series databases, engineers store metrics in general-purpose databases (PostgreSQL, MySQL, MongoDB). These work at small scale but degrade badly at high write rates: a metrics system writing 100K data points/second would require constant schema migrations, has no built-in data compression for repeating float sequences, and no automatic data expiration (old metrics accumulate forever). Time-series databases are purpose-built for append-only, time-indexed workloads with automatic downsampling, columnar compression, and -based data expiration.
Your team is building a backend service that collects server CPU and memory metrics from 5,000 machines, writing approximately 80,000 data points per second. After six months, the operations team notices the database is running out of disk space and query performance has significantly degraded. Which of the following is the most likely root cause if you are using a general-purpose relational database for this workload?
2. How It Works
Core Data Model
A time-series record has:
- Timestamp: nanosecond precision (InfluxDB) or microsecond (TimescaleDB)
- Metric name / Measurement: e.g.,
cpu_usage,http_request_count - Tags (indexed dimensions): e.g.,
host=web-01,region=us-east - Fields (unindexed values): e.g.,
value=72.4,count=4521
-- InfluxDB Line Protocol
cpu_usage,host=web-01,region=us-east value=72.4 1699920000000000000
^ ^ ^
tags (indexed) field value nanosecond timestamp
-- TimescaleDB (PostgreSQL hypertable)
INSERT INTO cpu_usage (time, host, region, value)
VALUES ('2024-01-15 08:30:00', 'web-01', 'us-east', 72.4);
InfluxDB Storage Engine (TSM)
InfluxDB 1.x/2.x uses TSM (Time-Structured Merge Tree) — a purpose-built storage engine inspired by LSM Trees but optimized for time-series:
- Write: Data is appended to (Write-Ahead Log) + in-memory Cache
- Cache flush: When Cache reaches size limit or reaches a threshold, data is written as a new TSM file
- TSM files: Read-only, columnar files. Data is organized by
(measurement, tag set, field key)→ sorted timestamp arrays. Uses type-specific compression: Gorilla XOR encoding for floats (stores only the changing bits between consecutive values — highly efficient for slowly-changing metrics), ZigZag for integers, bit-packing for booleans - : Background process merges TSM files (reduces file count, removes deleted data, improves query performance)
- Shards: Data is organized into time-based shards (e.g., 7-day boundaries). When a shard exceeds its retention period, the entire shard is deleted in O(1) — no row-by-row tombstoning
InfluxDB 3.0 (complete rewrite): The TSM engine was replaced by Apache Parquet on disk, with Apache DataFusion as the query engine and Apache Arrow Flight as the network protocol (the "FDAP stack"). The codebase was rewritten from Go to Rust. Flux query language was deprecated; SQL is now the primary query language.
TimescaleDB Architecture
TimescaleDB is a PostgreSQL extension that adds time-series optimizations transparently:
- Hypertables: User-visible table that automatically partitions data into "chunks" by time interval (e.g., 7-day chunks). is transparent — queries use standard SQL.
- Chunk pruning: The query planner skips chunks outside the requested time range, reducing I/O dramatically for time-bounded queries.
- Columnar compression: Older chunks are automatically converted to columnar format. Values for the same field across many rows are stored together, enabling type-specific compression. Real-world results: 90–95% size reduction (150 GB → 15 GB documented in production).
- Continuous aggregates: Pre-computed materialized views that auto-refresh as new data arrives — e.g., hourly averages pre-computed and stored for fast dashboard queries.
Mermaid: Write Path Comparison
Mermaid: System Architecture
A time-series database stores metrics from thousands of servers. After several months of operation, you notice that queries spanning the last 24 hours are fast, but queries covering data from 6 months ago are also fast — even though that historical data is rarely queried. Meanwhile, enforcing a 90-day data retention policy is nearly instantaneous and causes no performance disruption. Which architectural feature most directly explains both the fast historical queries AND the O(1) retention enforcement?
3. Variants & Comparisons
Time-Series Database Options
| System | Storage Model | Query Language | Best For | Managed? |
|---|---|---|---|---|
| InfluxDB 3 | Apache Parquet (columnar) | SQL, InfluxQL | IoT telemetry, industrial metrics, high-cardinality | InfluxDB Cloud |
| TimescaleDB | PostgreSQL chunks (columnar compressed) | SQL (full PostgreSQL) | Existing PostgreSQL teams, complex analytics + time-series | Timescale Cloud |
| Prometheus | Custom TSDB (WAL + mmap chunks) | PromQL | Kubernetes/infrastructure monitoring | Self-hosted + Thanos/Cortex for scale |
| VictoriaMetrics | Custom columnar storage | MetricsQL (PromQL compatible) | High-cardinality, Prometheus drop-in replacement | Self-hosted or managed |
| QuestDB | Custom columnar (column-per-field files) | SQL (PostgreSQL wire) | Ultra-fast ingestion, financial time-series | Managed (QuestDB Cloud) |
| Apache Druid | Segment-based columnar | SQL, Druid native | Real-time OLAP, sub-second queries on billions of rows | Self-hosted or managed |
| ClickHouse | MergeTree columnar | SQL | OLAP + time-series hybrid, log analytics | Self-hosted or managed |
InfluxDB vs TimescaleDB
| Dimension | InfluxDB 3 | TimescaleDB |
|---|---|---|
| Data Model | Measurements + tags + fields | Standard SQL tables (hypertables) |
| Query Language | SQL (via DataFusion), InfluxQL | Full PostgreSQL SQL |
| Storage | Apache Parquet | PostgreSQL (compressed chunks) |
| Cardinality | Handles very high cardinality (v3 removes limits) | Indexes scale with cardinality; very high cardinality needs tuning |
| Schema Flexibility | Schemaless (columns auto-created) | Schema-defined (standard SQL) |
| Joins | Limited | Full SQL JOINs with other PostgreSQL tables |
| Compression | High (Parquet columnar) | 90–95% reduction (columnar compression) |
| Ecosystem | InfluxDB ecosystem, FDAP stack | Full PostgreSQL ecosystem |
| Operational complexity | Medium (own system to learn) | Low for PostgreSQL teams |
Prometheus vs InfluxDB (Architecture Comparison)
| Dimension | Prometheus (pull) | InfluxDB (push) |
|---|---|---|
| Collection model | Server scrapes /metrics endpoints | Clients/agents push data to InfluxDB |
| Short-lived jobs | Requires Pushgateway | Natively supported |
| Best for | Kubernetes/infra monitoring | IoT, events, industrial telemetry |
| Query language | PromQL (functional) | SQL / InfluxQL |
| Long-term storage | Requires remote_write to Thanos/Cortex | Native clustering and retention |
| Alerting | Alertmanager (tightly integrated) | Kapacitor / external |
Your team currently runs a large PostgreSQL-based backend and wants to add time-series monitoring for application metrics. The team is comfortable with SQL and already has complex relational queries that join time-series data with business tables. Which time-series database would minimize operational overhead and best fit this scenario?
4. When to Use It (and When NOT To)
Use Time-Series DBs When:
- High write rates of timestamped data: 10K–1M+ data points/second from sensors, metrics agents, or telemetry streams. General-purpose databases struggle with this write volume without careful optimization.
- Time-range queries with aggregation are the dominant access pattern:
SELECT avg(cpu_usage) WHERE time > now()-1h GROUP BY time(5m). This is what TSDBs are optimized for; SQL databases require full-table scans or complex index strategies. - Automatic data expiration: Metrics older than 90 days are irrelevant but must be deleted. TSDBs handle this automatically via retention policies (shard-level deletion is O(1)).
- Downsampling / continuous aggregates: Keep raw 1-second data for 7 days, hourly averages for 1 year, daily averages forever. TimescaleDB continuous aggregates and InfluxDB tasks handle this natively.
- IoT / industrial telemetry: Thousands of devices each sending data every second. InfluxDB's tag-based data model and high-cardinality handling are purpose-built for this.
Do NOT Use Time-Series DBs When:
- Data is not primarily time-indexed: If time is just one of many fields (not the primary query dimension), a general-purpose database is more appropriate.
- You need complex JOINs across non-time entities: "Find all users who had CPU spikes AND submitted a support ticket in the same hour" — TimescaleDB can do this (full SQL), but InfluxDB cannot without external joins.
- Your data model is highly relational: Graph of users, orders, products — time-series databases have no concept of foreign keys or multi-table relational queries (InfluxDB) or limited support (TimescaleDB extends PostgreSQL).
- Write rate is modest (<1K/sec): PostgreSQL with a time-indexed table and pg_partman for handles this perfectly. Don't add a specialized system for low-volume time-series data.
Decision Triggers
| Constraint | Reach For |
|---|---|
| High-cardinality IoT / metrics at >10K writes/sec | InfluxDB 3 |
| Team already uses PostgreSQL, needs time-series | TimescaleDB |
| Kubernetes monitoring, Grafana + alerting | Prometheus + Grafana |
| Prometheus drop-in with better scalability | VictoriaMetrics |
| Ultra-fast ingestion + SQL, financial time-series | QuestDB |
| Real-time OLAP over time-series (sub-second aggregations) | Apache Druid or ClickHouse |
| Metrics at moderate scale (<1K/sec) | PostgreSQL + time index + pg_partman |
5. Real-World Usage
Tesla → InfluxDB (Manufacturing Telemetry)
Tesla uses InfluxDB Enterprise as its primary time-series database to collect and store data from manufacturing assets — assembly robots, industrial equipment, and production line sensors. The use case is classic IoT telemetry: each device emits data points at high frequency, data needs retention policies (recent = full resolution, old = downsampled), and dashboards aggregate metrics across device fleets. InfluxDB's tag-based data model naturally handles the host=machine-42, plant=fremont grouping for fleet-level queries.
InfluxDB in Observability Stacks (TICK Stack)
The TICK stack — Telegraf (agent), InfluxDB (storage), Chronograf (visualization), Kapacitor () — became a popular open-source alternative to commercial APM systems. Thousands of teams use Telegraf to collect server metrics (CPU, memory, disk, network) and push them to InfluxDB, with Grafana as the dashboard layer. The push-based model fits agents that run on each server and report outward.
TimescaleDB in Financial Tick Data
TimescaleDB's hypertable + continuous aggregates pattern is well-suited for financial tick data: millions of price ticks per day, needing both raw access (specific trade at 14:23:17.042) and aggregated views (OHLCV candles by minute/hour/day). The combination of PostgreSQL SQL expressiveness (window functions, complex JOINs with order/instrument metadata) and time-series optimizations (columnar compression for old ticks, chunk pruning for time-range queries) makes it a natural fit for financial analytics where SQL flexibility is non-negotiable.
A financial data platform stores millions of stock price ticks per day and needs to support two query patterns: retrieving a specific trade at an exact millisecond timestamp, and computing hourly OHLCV (open/high/low/close/volume) candles joined against an instruments metadata table. Which database approach is best suited for this combination of requirements?
6. Interview Cheat Sheet
5 Sentences to Show Deep Understanding
-
"Time-series databases are optimized for three things that general-purpose databases do poorly: high- append-only writes, time-range queries with aggregation, and automatic data expiration — a metrics system writing 100K points/second with 90-day retention would overwhelm PostgreSQL without specialized handling."
-
"InfluxDB's TSM engine (Time-Structured Merge Tree) is like an tuned for time-series: data is organized by (measurement, tag set, field), sorted by timestamp, and compressed with type-specific codecs — Gorilla XOR for floats, ZigZag for integers — achieving much better compression than generic gzip on the repeating float sequences typical of metrics."
-
"TimescaleDB's key insight is that time-series is just PostgreSQL with time-based — by hiding hypertable chunk management behind a standard SQL interface, teams get 90-95% compression and time-range query acceleration while keeping the full PostgreSQL ecosystem: JOINs, foreign keys, pg_stat, pg_dump."
-
"Cardinality is the Achilles heel of InfluxDB 1.x/2.x: too many unique tag combinations (e.g.,
user_idas a tag on a billion-user system) causes memory exhaustion in the time-series index. InfluxDB 3 addresses this by removing the in-memory cardinality index entirely, using Parquet files that handle high cardinality natively." -
"Prometheus is pull-based (server scrapes targets) and optimized for Kubernetes , where and scrape configs are natural. InfluxDB is push-based and optimized for IoT and industrial telemetry, where sensors push outbound to a central collector. Choosing between them comes down to collection model and query complexity."
Common Follow-Up Questions
Q: What is the cardinality problem in time-series databases?
A: Cardinality refers to the number of unique time-series (unique combinations of metric name + all tag values). In InfluxDB 1.x/2.x, each unique series required an entry in an in-memory inverted index. If you use user_id as a tag in a billion-user system, the index holds a billion entries — causing OOM. The fix: use user_id as a field (unindexed) not a tag, or upgrade to InfluxDB 3.0 which removes the cardinality limit.
Q: How does data retention work in InfluxDB? A: InfluxDB organizes data into time-based shards (e.g., 7-day boundaries). A retention service runs every 30 minutes and deletes entire shards that have exceeded the retention period. This is O(1) file deletion — much more efficient than row-level tombstoning in general-purpose databases.
Q: When would you use TimescaleDB instead of InfluxDB? A: When you need: (1) full SQL with JOINs across relational and time-series data; (2) PostgreSQL tooling (pg_dump, logical , existing drivers); (3) complex analytics that go beyond simple aggregations; (4) an existing PostgreSQL team that doesn't want to learn a new database. InfluxDB wins on: pure write , native high-cardinality support (v3), and the IoT/line-protocol ecosystem.
Q: What is downsampling and why does it matter? A: Downsampling is the process of aggregating high-resolution data into lower-resolution summaries as data ages. Example: keep 1-second raw metrics for 7 days, then downsample to 1-minute averages for 6 months, then to 1-hour averages forever. This dramatically reduces storage: 86,400 points/day at 1-second → 1,440 at 1-minute → 24 at 1-hour. Both InfluxDB (tasks) and TimescaleDB (continuous aggregates) support this natively.
Connections to Other Building Blocks
- Write-Ahead Log (): TSDBs use WALs for , same as PostgreSQL and . InfluxDB's is an append-only log flushed before acknowledging a write.
- LSM Trees: InfluxDB's TSM is conceptually an adapted for time-series. The same , level, and bloom filter concepts apply.
- Message Queues (): High-volume telemetry pipelines typically flow: sensors → Kafka (buffer/) → Telegraf/consumer → InfluxDB. Kafka provides protection; InfluxDB provides queryable storage.
- Caching: Grafana dashboards often add Redis in front of TSDB queries for dashboard-level caching — the same time-range query (last 24h CPU avg) hits the cache on repeated loads.
- : TSDBs use time-based (temporal ) rather than key-based sharding. Query pruning is trivial:
WHERE time > Tskips all shards before T.
Glossary History
Click dotted jargon to save explanations here.
Glossary History
Click dotted jargon to save explanations here.