Back to Blog
IoT Engineering

Time-Series Databases for IoT: InfluxDB vs TimescaleDB vs AWS Timestream

The wrong time-series database can cost you 10x in cloud bills or leave your team fighting a query language nobody knows. This comparison gives IoT engineers a practical framework to choose between InfluxDB, TimescaleDB, and AWS Timestream.

March 4, 2024
13 min read
InfluxDBTimescaleDBAWS TimestreamTime-Series

Time-Series Databases for IoT: InfluxDB vs TimescaleDB vs AWS Timestream

Your IoT sensors generate timestamps and values — a perfect fit for a time-series database. But InfluxDB, TimescaleDB, and AWS Timestream make radically different trade-offs in query language, cost model, and operational complexity. Picking wrong costs real money and team frustration.

What Makes a Time-Series Database Different

Relational databases store data in row order. Time-series databases organize data by time and measurement, enabling:

  • Compressed columnar storage: sensor readings are repetitive — temperature rarely jumps 100 degrees. Column compression achieves 10–50x over row storage.
  • Automatic downsampling: keep raw data for 7 days, hourly averages for 90 days, daily averages forever — without manual scripts.
  • Time-bucketing queries: "average temperature per 15-minute bucket over the last 24 hours" is a first-class operation.
  • Retention policies: automatic data expiry without application-level cleanup jobs.
  • InfluxDB (v2/v3)

    InfluxDB is the most widely deployed dedicated time-series database in IoT. Its data model uses measurements, tags (indexed metadata), and fields (time-series values).

    Write API:

    // Node.js: write to InfluxDB v2
    const { InfluxDB, Point } = require('@influxdata/influxdb-client')

    const client = new InfluxDB({ url: process.env.INFLUXDB_URL, token: process.env.INFLUXDB_TOKEN, }) const writeApi = client.getWriteApi('my-org', 'sensors', 'ms') writeApi.useDefaultTags({ gatewayId: 'gw-001' })

    function writeSensorData(deviceId, temperature, humidity, battery) { const point = new Point('environment') .tag('deviceId', deviceId) .tag('location', 'building-a') .floatField('temperature', temperature) .floatField('humidity', humidity) .intField('battery', battery) writeApi.writePoint(point) }

    // Flush every 1 second or 5000 points, whichever comes first setInterval(() => writeApi.flush(), 1000)

    Flux query (InfluxDB v2):

    // 15-minute average temperature for the last 24 hours
    from(bucket: "sensors")
      |> range(start: -24h)
      |> filter(fn: (r) => r._measurement == "environment" and r._field == "temperature")
      |> filter(fn: (r) => r.deviceId == "sensor-42")
      |> aggregateWindow(every: 15m, fn: mean, createEmpty: false)
      |> yield(name: "mean")
    

    Strengths:

  • Excellent write throughput (500k+ points/sec on adequate hardware)
  • Flux is powerful for complex transformations
  • Native Grafana datasource with one-click setup
  • Continuous queries / Tasks for automatic downsampling
  • Weaknesses:

  • Flux has a steep learning curve — it's a functional language, not SQL
  • InfluxDB v3 is a significant breaking change from v2
  • Self-hosted operational burden (disk management, compaction)
  • Best for: Teams comfortable with a dedicated TSDB tool, needing high write throughput and complex time-series math.

    TimescaleDB

    TimescaleDB is PostgreSQL with time-series superpowers. If your team already knows SQL and PostgreSQL, the learning curve is near-zero.

    -- Create a hypertable (auto-partitioned by time)
    CREATE TABLE sensor_readings (
      time        TIMESTAMPTZ NOT NULL,
      device_id   TEXT        NOT NULL,
      temperature DOUBLE PRECISION,
      humidity    DOUBLE PRECISION,
      battery     INTEGER
    );
    SELECT create_hypertable('sensor_readings', 'time', chunk_time_interval => INTERVAL '1 day');

    -- Add compression (50–70% size reduction) ALTER TABLE sensor_readings SET ( timescaledb.compress, timescaledb.compress_segmentby = 'device_id' ); SELECT add_compression_policy('sensor_readings', INTERVAL '7 days');

    -- Continuous aggregate: hourly averages CREATE MATERIALIZED VIEW hourly_averages WITH (timescaledb.continuous) AS SELECT time_bucket('1 hour', time) AS bucket, device_id, AVG(temperature) AS avg_temp, AVG(humidity) AS avg_humidity FROM sensor_readings GROUP BY bucket, device_id WITH NO DATA;

    SELECT add_continuous_aggregate_policy('hourly_averages', start_offset => INTERVAL '3 hours', end_offset => INTERVAL '1 hour', schedule_interval => INTERVAL '1 hour');

    Query with familiar SQL:

    -- 15-minute averages for the last 24 hours, with gap filling
    SELECT
      time_bucket_gapfill('15 minutes', time) AS bucket,
      device_id,
      interpolate(AVG(temperature)) AS temperature
    FROM sensor_readings
    WHERE device_id = 'sensor-42'
      AND time > NOW() - INTERVAL '24 hours'
    GROUP BY bucket, device_id
    ORDER BY bucket;
    

    Strengths:

  • Full SQL — no new language to learn
  • JOIN with your existing relational data (devices table, users table)
  • All PostgreSQL extensions work (PostGIS for geospatial, pgcrypto, etc.)
  • Mature ecosystem: pgAdmin, existing ORM support
  • Weaknesses:

  • Lower raw write throughput than InfluxDB for pure time-series workloads
  • Requires PostgreSQL ops knowledge at scale
  • Best for: Teams already running PostgreSQL, or systems where sensor data joins relational data frequently.

    AWS Timestream

    Timestream is a fully managed serverless TSDB. No servers, no disk management, automatic scaling.

    // Node.js: write to AWS Timestream
    const { TimestreamWriteClient, WriteRecordsCommand } = require('@aws-sdk/client-timestream-write')

    const client = new TimestreamWriteClient({ region: 'us-east-1' })

    async function writeToTimestream(deviceId, temperature, humidity) { const now = BigInt(Date.now()).toString()

    await client.send(new WriteRecordsCommand({ DatabaseName: 'IoTDatabase', TableName: 'SensorReadings', CommonAttributes: { Dimensions: [{ Name: 'deviceId', Value: deviceId }], Time: now, TimeUnit: 'MILLISECONDS', }, Records: [ { MeasureName: 'temperature', MeasureValue: String(temperature), MeasureValueType: 'DOUBLE' }, { MeasureName: 'humidity', MeasureValue: String(humidity), MeasureValueType: 'DOUBLE' }, ], })) }

    Query (SQL-compatible):

    -- 15-minute averages, Timestream syntax
    SELECT
      bin(time, 15m) AS bucket,
      deviceId,
      AVG(measure_value::double) AS avg_temperature
    FROM "IoTDatabase"."SensorReadings"
    WHERE measure_name = 'temperature'
      AND deviceId = 'sensor-42'
      AND time BETWEEN ago(24h) AND now()
    GROUP BY bin(time, 15m), deviceId
    ORDER BY bucket
    

    Strengths:

  • Zero operational overhead — truly serverless
  • Deep AWS integration (IoT Core Rules, Lambda, Grafana via plugin)
  • Automatic tiering: hot memory store (recent data) + cheap S3-backed magnetic store (historical)
  • Weaknesses:

  • Cost model is complex and can surprise at scale ($0.50/GB ingested + $0.036/GB stored in memory + query scan costs)
  • Less flexible for complex analytics than InfluxDB Flux
  • Grafana plugin is less mature than native InfluxDB support
  • Best for: AWS-native deployments, teams that want zero ops burden, and systems with manageable data volumes.

    Head-to-Head Comparison

    | Dimension | InfluxDB | TimescaleDB | Timestream | |-----------|----------|-------------|------------| | Write throughput | Excellent | Good | Good | | Query language | Flux (custom) | SQL | SQL-like | | Ops overhead | Medium | Medium | Zero | | Grafana support | Native | Via PostgreSQL | Plugin | | Cost at 1M readings/day | ~$50/mo (cloud) | ~$30/mo (EC2) | ~$80/mo | | Data joins (relational) | Poor | Excellent | Poor | | AWS-native | No | No | Yes |

    Retention and Downsampling

    All three support automatic retention, but the configuration differs significantly.

    For Timestream, set it in the table configuration: memory store retention (hours), magnetic store retention (days). For InfluxDB, define retention policies in the bucket settings. For TimescaleDB, use add_retention_policy('sensor_readings', INTERVAL '90 days').

    The sweet spot for most IoT deployments: raw data for 30 days, 1-hour aggregates for 1 year, 1-day aggregates forever.

    For the full picture of how these databases fit into your data pipeline, see [IoT Data Pipeline: Sensor to Dashboard](/blog/iot-data-pipeline-sensor-to-dashboard).

    For real-time alerting on top of this data, see [Real-Time IoT Alerting](/blog/realtime-iot-alerting-threshold-anomaly).

    Need help with IoT data storage architecture? [Contact Code Caracal](/contact) — we've shipped these systems for clients across 15+ countries.

    Written by CodeCaracal Engineering

    We write from production experience — every technique in our articles has been deployed to real clients. No academic theory.

    More Articles

    Business · 12 min read

    IoT Device Compliance: FCC, CE, and Product Certification Guide for Hardware Startups

    Business · 11 min read

    What to Look for When Hiring an IoT Development Partner: 8 Critical Criteria

    Business · 11 min read

    IoT MVP to Production: Realistic Timeline and Budget for Hardware Startups

    Business · 11 min read

    IoT Development Agency vs Building In-House: A Decision Framework for Founders

    IoT Dashboard · 13 min read

    Next.js IoT Analytics Dashboard: From Sensor Data to Production App

    Business · 11 min read

    How Much Does It Cost to Build an IoT Product in 2024? A Realistic Breakdown

    IoT Dashboard · 11 min read

    IoT Dashboard UX: Design Principles for Industrial Monitoring Interfaces

    IoT Dashboard · 12 min read

    Node.js WebSocket Server: The Real-Time Backend for IoT Dashboards

    Cloud & DevOps · 12 min read

    Containerizing IoT Backend Services with Docker: From Dev to Production

    IoT Dashboard · 14 min read

    Grafana + InfluxDB IoT Monitoring: Complete Production Setup Guide

    IoT Dashboard · 12 min read

    Building Real-Time IoT Dashboards with React and Recharts

    Cloud & DevOps · 13 min read

    CI/CD for Embedded Firmware: Automated Build, Test, and OTA Release Pipeline

    Mobile Development · 12 min read

    Flutter Offline-First IoT Apps: Hive + Sync Architecture That Works in the Field

    Cloud & DevOps · 14 min read

    Terraform for IoT Infrastructure: Provisioning AWS IoT Core, Lambda, and InfluxDB as Code

    Mobile Development · 10 min read

    Flutter IoT Alerts: Firebase Push Notifications for Device Events

    Cloud & DevOps · 12 min read

    Deploying IoT Backends on AWS: ECS Fargate vs Lambda vs EC2 Decision Guide

    Mobile Development · 11 min read

    Flutter + MQTT: Building Production IoT Mobile Apps That Scale

    Mobile Development · 13 min read

    Flutter BLE: Building a Bluetooth IoT Controller App from Scratch

    Cloud & DevOps · 13 min read

    AWS IoT Core vs Azure IoT Hub vs Google Cloud IoT: 2024 Honest Comparison

    IoT Engineering · 13 min read

    Kafka vs RabbitMQ for IoT: Choosing the Right Message Queue for High-Volume Telemetry

    IoT Engineering · 14 min read

    IoT System Testing: Unit, Integration, Hardware-in-the-Loop, and End-to-End

    IoT Engineering · 14 min read

    Predictive Maintenance with IoT Sensor Data: From Threshold to Machine Learning

    Embedded Systems · 14 min read

    IoT Bootloader Design: Secure Boot, A/B Partitions, and Reliable OTA Recovery

    IoT Engineering · 14 min read

    Multi-Tenant IoT Platform Architecture: Isolation, Scaling, and Data Partitioning

    Embedded Systems · 14 min read

    Memory Management in Embedded Firmware: Avoiding Heap Fragmentation and Stack Overflows

    IoT Engineering · 13 min read

    IoT Cost Optimization: How We Cut AWS IoT Bills by 60% Without Sacrificing Reliability

    IoT Engineering · 12 min read

    Edge Computing in IoT: When to Process On-Device vs In the Cloud

    IoT Engineering · 13 min read

    Digital Twins for IoT: Building a Virtual Mirror of Your Physical Devices

    Embedded Systems · 14 min read

    ESP32 Deep Sleep Mastery: Cutting Power Consumption from 240mA to 10µA

    IoT Engineering · 10 min read

    MQTT QoS 0, 1, and 2 Explained: Choosing the Right Level for IoT

    IoT Engineering · 14 min read

    IoT Monitoring and Observability: Metrics, Logs, and Distributed Tracing

    Embedded Systems · 14 min read

    Debugging Embedded Firmware: JTAG, GDB, Logic Analyzers, and Serial Tracing

    IoT Engineering · 12 min read

    WebSocket vs MQTT vs Server-Sent Events: Real-Time IoT Protocol Deep Dive

    Embedded Systems · 13 min read

    STM32 HAL vs Low-Level Drivers: When the Abstraction Costs You Too Much

    IoT Engineering · 13 min read

    IoT Data Pipeline: From Raw Sensor Reading to Live Dashboard in Under 100ms

    IoT Engineering · 13 min read

    Zero-Touch IoT Device Provisioning: Scaling from 10 to 100,000 Devices

    Embedded Systems · 13 min read

    UART vs SPI vs I2C: Choosing the Right Protocol for Sensor Integration

    IoT Engineering · 12 min read

    Real-Time IoT Alerting: From Simple Thresholds to ML Anomaly Detection

    Embedded Systems · 12 min read

    ESP32 Partition Table: Designing Flash Layout for Production Firmware

    IoT Engineering · 12 min read

    IoT Architecture Patterns: Hub-and-Spoke, Mesh, and Edge-Cloud Hybrid

    Embedded Systems · 13 min read

    IoT Battery Life Optimization: Engineering Devices That Last Years on a Single Charge

    Security · 14 min read

    Zero-Trust Security for Embedded IoT: Why Your Devices Are Probably Vulnerable

    Embedded Systems · 14 min read

    FreeRTOS on ESP32: Task Scheduling, Queues, and Resource Management for IoT

    IoT Engineering · 12 min read

    Building a Production IoT Gateway with Raspberry Pi and Node.js

    Embedded Systems · 13 min read

    ESP32 vs STM32: Choosing the Right Microcontroller for Your IoT Project

    Mobile Development · 10 min read

    Flutter + WebSocket: Building Real-Time IoT Dashboards That Don't Stutter

    IoT Engineering · 13 min read

    IoT Fleet Management at Scale: AWS IoT Core Device Registry and Provisioning

    IoT Engineering · 11 min read

    MQTT vs HTTP for IoT: Which Protocol Wins in Production?

    IoT Engineering · 12 min read

    ESP32 → MQTT → AWS IoT Core: The Production-Grade Architecture Guide

    Let's Build Together

    Got an IoT challenge?
    We've shipped it.

    Whether you need a fleet to track, a factory to monitor, or a farm to automate — our team has done it before and we'd love to build it with you. Typical response time: under 24 hours.

    No upfront commitment99.9% uptime SLANDA on requestFixed-price options