Convert Figma logo to code with AI

timescale logotimescaledb

A time-series database for high-performance real-time analytics packaged as a Postgres extension

21,858
1,043
21,858
461

Top Related Projects

31,325

Scalable datastore for metrics, events, and real-time analytics

13,965

Apache Druid: a high performance real-time analytics database.

The Prometheus monitoring system and time series database.

16,931

QuestDB is a high performance, open-source, time-series database

ClickHouse® is a real-time analytics database management system

6,078

Apache Pinot - A realtime distributed OLAP datastore

Quick Overview

TimescaleDB is an open-source database designed to make SQL scalable for time-series data. It is implemented as an extension to PostgreSQL, providing automatic partitioning across time and space, as well as full SQL support. TimescaleDB is optimized for fast ingest and complex queries, making it ideal for IoT, financial data, and monitoring applications.

Pros

  • Seamless integration with PostgreSQL, leveraging its robust ecosystem and features
  • Automatic time-based partitioning for improved query performance and data management
  • Supports both time-series and relational workloads in a single database
  • Offers advanced features like continuous aggregates, data retention policies, and compression

Cons

  • Requires PostgreSQL as a base system, which may not be suitable for all use cases
  • Learning curve for users not familiar with PostgreSQL or time-series databases
  • Performance may not match specialized time-series databases in certain scenarios
  • Limited support for distributed deployments compared to some other time-series solutions

Code Examples

  1. Creating a hypertable:
CREATE TABLE sensor_data (
  time        TIMESTAMPTZ       NOT NULL,
  sensor_id   INTEGER           NOT NULL,
  temperature DOUBLE PRECISION  NULL,
  humidity    DOUBLE PRECISION  NULL
);

SELECT create_hypertable('sensor_data', 'time');
  1. Inserting data into a hypertable:
INSERT INTO sensor_data (time, sensor_id, temperature, humidity)
VALUES (NOW(), 1, 25.6, 47.3),
       (NOW() - INTERVAL '1 hour', 2, 23.4, 51.2);
  1. Querying time-series data with time bucketing:
SELECT time_bucket('1 hour', time) AS hour,
       AVG(temperature) AS avg_temp,
       AVG(humidity) AS avg_humidity
FROM sensor_data
WHERE time > NOW() - INTERVAL '24 hours'
GROUP BY hour
ORDER BY hour;

Getting Started

To get started with TimescaleDB:

  1. Install PostgreSQL and TimescaleDB extension (follow instructions on the official website).
  2. Create a new database and enable the extension:
CREATE DATABASE timeseries_db;
\c timeseries_db
CREATE EXTENSION IF NOT EXISTS timescaledb;
  1. Create a table and convert it to a hypertable:
CREATE TABLE metrics (
  time TIMESTAMPTZ NOT NULL,
  device_id INTEGER,
  value DOUBLE PRECISION
);

SELECT create_hypertable('metrics', 'time');
  1. Start inserting and querying data using standard SQL commands.

Competitor Comparisons

31,325

Scalable datastore for metrics, events, and real-time analytics

Pros of InfluxDB

  • Purpose-built for time-series data, offering optimized performance for time-based queries
  • Flexible data model with tags and fields, allowing for efficient storage and querying of high-cardinality data
  • Built-in data retention policies and continuous queries for automated data management

Cons of InfluxDB

  • Limited support for complex joins and relational queries compared to TimescaleDB's SQL capabilities
  • Lacks some advanced PostgreSQL features that TimescaleDB inherits, such as full ACID compliance and rich indexing options

Code Comparison

InfluxDB query example:

SELECT mean("value") FROM "cpu_usage"
WHERE "host" = 'server01' AND time >= now() - 1h
GROUP BY time(5m)

TimescaleDB query example:

SELECT time_bucket('5 minutes', time) AS five_min,
       avg(value) AS mean_value
FROM cpu_usage
WHERE host = 'server01' AND time >= now() - interval '1 hour'
GROUP BY five_min
ORDER BY five_min;

Both databases offer efficient time-series querying, but TimescaleDB uses standard SQL syntax, while InfluxDB uses its own query language (InfluxQL or Flux). TimescaleDB's SQL approach may be more familiar to developers with relational database experience.

13,965

Apache Druid: a high performance real-time analytics database.

Pros of Druid

  • Designed for real-time analytics on large-scale streaming data
  • Highly scalable and distributed architecture
  • Supports complex aggregations and fast ad-hoc queries

Cons of Druid

  • Steeper learning curve and more complex setup
  • Limited support for updating or deleting existing data
  • Higher resource requirements for smaller datasets

Code Comparison

Druid Query Example

SELECT COUNT(*) AS count,
       SUM(price) AS total_price
FROM transactions
WHERE timestamp >= CURRENT_TIMESTAMP - INTERVAL '1' DAY
GROUP BY product_id
HAVING COUNT(*) > 100

TimescaleDB Query Example

SELECT COUNT(*) AS count,
       SUM(price) AS total_price
FROM transactions
WHERE time > NOW() - INTERVAL '1 day'
GROUP BY product_id
HAVING COUNT(*) > 100

Both Druid and TimescaleDB are designed for time-series data, but they have different strengths. Druid excels in real-time analytics and scalability for large datasets, while TimescaleDB offers better SQL compatibility and easier integration with existing PostgreSQL ecosystems. The code examples show similar query syntax, with minor differences in time-related functions and column naming conventions.

The Prometheus monitoring system and time series database.

Pros of Prometheus

  • Built-in alerting and monitoring system with a powerful query language (PromQL)
  • Native support for multi-dimensional data and time series
  • Extensive ecosystem with various exporters and integrations

Cons of Prometheus

  • Limited long-term storage capabilities
  • Lacks built-in downsampling and data retention policies
  • Scaling horizontally can be challenging

Code Comparison

TimescaleDB (SQL query):

SELECT time_bucket('1 hour', time) AS hour,
       avg(temperature) AS avg_temp
FROM sensor_data
WHERE time > NOW() - INTERVAL '1 day'
GROUP BY hour
ORDER BY hour;

Prometheus (PromQL query):

avg_over_time(temperature[1h])

Additional Notes

TimescaleDB is an extension of PostgreSQL, offering advanced time-series capabilities while maintaining full SQL compatibility. It excels in handling large volumes of time-series data with efficient storage and querying.

Prometheus, on the other hand, is a complete monitoring and alerting toolkit designed for reliability and scalability in dynamic environments. It's particularly well-suited for microservices architectures and cloud-native applications.

While both handle time-series data, they serve different primary purposes: TimescaleDB as a database solution and Prometheus as a monitoring system. The choice between them depends on specific use cases and requirements.

16,931

QuestDB is a high performance, open-source, time-series database

Pros of QuestDB

  • Designed for high-performance time-series data processing with zero dependencies
  • Supports SQL with extensions for time-series operations
  • Offers out-of-the-box web console for data exploration and visualization

Cons of QuestDB

  • Smaller ecosystem and community compared to TimescaleDB
  • Limited advanced features like continuous aggregates and data retention policies
  • Less mature and battle-tested in production environments

Code Comparison

QuestDB SQL query:

SELECT date_trunc('hour', timestamp) AS hour,
       avg(temperature) AS avg_temp
FROM sensors
WHERE location = 'NYC'
GROUP BY hour
ORDER BY hour DESC
LIMIT 24;

TimescaleDB SQL query:

SELECT time_bucket('1 hour', timestamp) AS hour,
       avg(temperature) AS avg_temp
FROM sensors
WHERE location = 'NYC'
GROUP BY hour
ORDER BY hour DESC
LIMIT 24;

Both databases support SQL queries for time-series data, with slight differences in function names (e.g., date_trunc vs time_bucket). TimescaleDB leverages PostgreSQL's ecosystem, while QuestDB focuses on a lightweight, high-performance approach for time-series data.

ClickHouse® is a real-time analytics database management system

Pros of ClickHouse

  • Exceptional performance for analytical queries on large datasets
  • Highly scalable and distributed architecture
  • Supports a wide range of data types and storage engines

Cons of ClickHouse

  • Steeper learning curve due to its unique query language and architecture
  • Limited support for real-time updates and deletes
  • Less suitable for OLTP workloads compared to TimescaleDB

Code Comparison

ClickHouse query example:

SELECT date, count() AS count
FROM events
GROUP BY date
ORDER BY date

TimescaleDB query example:

SELECT time_bucket('1 day', time) AS date, count(*)
FROM events
GROUP BY date
ORDER BY date

Both examples show a simple time-based aggregation query. ClickHouse uses its native syntax, while TimescaleDB extends PostgreSQL with time-bucket functions.

ClickHouse is optimized for analytical queries on large datasets, offering superior performance for complex aggregations. TimescaleDB, built on PostgreSQL, provides a more familiar SQL interface and better support for real-time updates and OLTP workloads.

Choose ClickHouse for high-performance analytics on massive datasets, and TimescaleDB for a balance between time-series capabilities and traditional relational database features.

6,078

Apache Pinot - A realtime distributed OLAP datastore

Pros of Pinot

  • Designed for real-time analytics with low latency querying on large datasets
  • Supports multiple data ingestion methods, including streaming and batch
  • Highly scalable and distributed architecture for handling massive data volumes

Cons of Pinot

  • Steeper learning curve and more complex setup compared to TimescaleDB
  • Requires more resources and infrastructure to run effectively
  • Less mature ecosystem and fewer integrations with existing tools

Code Comparison

TimescaleDB (SQL-based):

CREATE TABLE metrics (
  time TIMESTAMPTZ NOT NULL,
  device_id INTEGER,
  temperature FLOAT,
  cpu_usage FLOAT
);

SELECT time_bucket('1 hour', time) AS hour,
       AVG(temperature) AS avg_temp
FROM metrics
WHERE time > NOW() - INTERVAL '24 hours'
GROUP BY hour
ORDER BY hour;

Pinot (PQL-based):

SELECT DATETIMECONVERT(ts, '1:MILLISECONDS:EPOCH', '1:HOURS:EPOCH', '1:HOURS') AS hour,
       AVG(temperature) AS avg_temp
FROM metrics
WHERE ts > FromDateTime(now(), 'yyyy-MM-dd HH:mm:ss') - 24 * 3600 * 1000
GROUP BY hour
ORDER BY hour
LIMIT 10000

Both TimescaleDB and Pinot offer powerful solutions for time-series data, with TimescaleDB providing a more familiar PostgreSQL-based approach and Pinot focusing on real-time analytics at scale.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Tiger Data logo

TimescaleDB is a PostgreSQL extension for high-performance real-time analytics on time-series and event data

Docs SLACK Try TimescaleDB for free

Quick Start with TimescaleDB

Get started with TimescaleDB in under 10 minutes. This guide will help you run TimescaleDB locally, create your first hypertable with columnstore enabled, write data to the columnstore, and see instant analytical query performance.

What You'll Learn

  • How to run TimescaleDB with a one-line install or Docker command
  • How to create a hypertable with columnstore enabled
  • How to insert data directly to the columnstore
  • How to execute analytical queries

Prerequisites

  • Docker installed on your machine
  • 8GB RAM recommended
  • psql client (included with PostgreSQL) or any PostgreSQL client like pgAdmin

Step 1: Start TimescaleDB

You have two options to start TimescaleDB:

Option 1: One-line install (Recommended)

The easiest way to get started:

Important: This script is intended for local development and testing only. Do not use it for production deployments. For production-ready installation options, see the TimescaleDB installation guide.

Linux/Mac:

curl -sL https://tsdb.co/start-local | sh

This command:

  • Downloads and starts TimescaleDB (if not already downloaded)
  • Exposes PostgreSQL on port 6543 (a non-standard port to avoid conflicts with other PostgreSQL instances on port 5432)
  • Automatically tunes settings for your environment using timescaledb-tune
  • Sets up a persistent data volume

Option 2: Manual Docker command also used for Windows

Alternatively, you can run TimescaleDB directly with Docker:

docker run -d --name timescaledb \
    -p 6543:5432 \
    -e POSTGRES_PASSWORD=password \
    timescale/timescaledb-ha:pg18

Note: We use port 6543 (mapped to container port 5432) to avoid conflicts if you have other PostgreSQL instances running on the standard port 5432.

Wait about 1-2 minutes for TimescaleDB to download & initialize.

Step 2: Connect to TimescaleDB

Connect using psql:

psql -h localhost -p 6543 -U postgres
# When prompted, enter password: password

You should see the PostgreSQL prompt. Verify TimescaleDB is installed:

SELECT extname, extversion FROM pg_extension WHERE extname = 'timescaledb';

Expected output:

   extname   | extversion
-------------+------------
 timescaledb | 2.x.x

Prefer a GUI? If you'd rather use a graphical tool instead of the command line, you can download pgAdmin and connect to TimescaleDB using the same connection details (host: localhost, port: 6543, user: postgres, password: password).

Step 3: Create Your First Hypertable

Let's create a hypertable for IoT sensor data with columnstore enabled:

-- Create a hypertable with automatic columnstore
CREATE TABLE sensor_data (
    time TIMESTAMPTZ NOT NULL,
    sensor_id TEXT NOT NULL,
    temperature DOUBLE PRECISION,
    humidity DOUBLE PRECISION,
    pressure DOUBLE PRECISION
) WITH (
    tsdb.hypertable
);
-- create index
CREATE INDEX idx_sensor_id_time ON sensor_data(sensor_id, time DESC);

tsdb.hypertable - Converts this into a TimescaleDB hypertable

See more:

Step 4: Insert Sample Data

Let's add some sample sensor readings:

-- Enable timing to see time to execute queries
\timing on

-- Insert sample data for multiple sensors
-- SET timescaledb.enable_direct_compress_insert = on to insert data directly to the columnstore (columnnar format for performance)
SET timescaledb.enable_direct_compress_insert = on;
INSERT INTO sensor_data (time, sensor_id, temperature, humidity, pressure)
SELECT
    time,
    'sensor_' || ((random() * 9)::int + 1),
    20 + (random() * 15),
    40 + (random() * 30),
    1000 + (random() * 50)
FROM generate_series(
    NOW() - INTERVAL '90 days',
    NOW(),
    INTERVAL '1 seconds'
) AS time;

-- Once data is inserted into the columnstore we optimize the order and structure 
-- this compacts and orders the data in the chunks for optimal query performance and compression
DO $$
DECLARE ch TEXT;
BEGIN
    FOR ch IN SELECT show_chunks('sensor_data') LOOP
        CALL convert_to_columnstore(ch, recompress := true);
    END LOOP;
END $$;

This generates ~7,776,001 readings across 10 sensors over the past 90 days.

Verify the data was inserted:

SELECT COUNT(*) FROM sensor_data;

Step 5: Run Your First Analytical Queries

Now let's run some analytical queries that showcase TimescaleDB's performance:

-- Enable query timing to see performance
\timing on

-- Query 1: Average readings per sensor over the last 7 days
SELECT
    sensor_id,
    COUNT(*) as readings,
    ROUND(AVG(temperature)::numeric, 2) as avg_temp,
    ROUND(AVG(humidity)::numeric, 2) as avg_humidity,
    ROUND(AVG(pressure)::numeric, 2) as avg_pressure
FROM sensor_data
WHERE time > NOW() - INTERVAL '7 days'
GROUP BY sensor_id
ORDER BY sensor_id;

-- Query 2: Hourly averages using time_bucket 
-- Time buckets enable you to aggregate data in hypertables by time interval and calculate summary values.
SELECT
    time_bucket('1 hour', time) AS hour,
    sensor_id,
    ROUND(AVG(temperature)::numeric, 2) as avg_temp,
    ROUND(AVG(humidity)::numeric, 2) as avg_humidity
FROM sensor_data
WHERE time > NOW() - INTERVAL '24 hours'
GROUP BY hour, sensor_id
ORDER BY hour DESC, sensor_id
LIMIT 20;

-- Query 3: Daily statistics across all sensors
SELECT
    time_bucket('1 day', time) AS day,
    COUNT(*) as total_readings,
    ROUND(AVG(temperature)::numeric, 2) as avg_temp,
    ROUND(MIN(temperature)::numeric, 2) as min_temp,
    ROUND(MAX(temperature)::numeric, 2) as max_temp
FROM sensor_data
GROUP BY day
ORDER BY day DESC
LIMIT 10;

-- Query 4: Latest reading for each sensor
-- Highlights the value of Skipscan executing in under 100ms without skipscan it takes over 5sec
SELECT DISTINCT ON (sensor_id)
    sensor_id,
    time,
    ROUND(temperature::numeric, 2) as temperature,
    ROUND(humidity::numeric, 2) as humidity,
    ROUND(pressure::numeric, 2) as pressure
FROM sensor_data
ORDER BY sensor_id, time DESC;

Notice how fast these analytical queries run, even with aggregations across millions of rows. This is the power of TimescaleDB's columnstore.

What's Happening Behind the Scenes?

TimescaleDB automatically:

  • Partitions your data into time-based chunks for efficient querying
  • Write directly to columnstore using columnar storage (90%+ compression typical) and faster vectorized queries
  • Optimizes queries by only scanning relevant time ranges and columns
  • Enables time_bucket() - a powerful function for time-series aggregation

See more:

Next Steps

Now that you've got the basics, explore more:

Create Continuous Aggregates

Continuous aggregates make real-time analytics run faster on very large datasets. They continuously and incrementally refresh a query in the background, so that when you run such query, only the data that has changed needs to be computed, not the entire dataset. This is what makes them different from regular PostgreSQL materialized views, which cannot be incrementally materialized and have to be rebuilt from scratch every time you want to refresh them.

Let's create a continuous aggregate for hourly sensor statistics:

Step 1: Create the Continuous Aggregate

CREATE MATERIALIZED VIEW sensor_data_hourly
WITH (timescaledb.continuous) AS
SELECT
    time_bucket('1 hour', time) AS hour,
    sensor_id,
    AVG(temperature) AS avg_temp,
    AVG(humidity) AS avg_humidity,
    AVG(pressure) AS avg_pressure,
    MIN(temperature) AS min_temp,
    MAX(temperature) AS max_temp,
    COUNT(*) AS reading_count
FROM sensor_data
GROUP BY hour, sensor_id;

This creates a materialized view that pre-aggregates your sensor data into hourly buckets. The view is automatically populated with existing data.

Step 2: Add a Refresh Policy

To keep the continuous aggregate up-to-date as new data arrives, add a refresh policy:

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

This policy:

  • Refreshes the continuous aggregate every hour
  • Processes data from 3 hours ago up to 1 hour ago (leaving the most recent hour for real-time queries)
  • Only processes new or changed data incrementally

Step 3: Query the Continuous Aggregate

Now you can query the pre-aggregated data for much faster results:

-- Get hourly averages for the last 24 hours
SELECT
    hour,
    sensor_id,
    ROUND(avg_temp::numeric, 2) AS avg_temp,
    ROUND(avg_humidity::numeric, 2) AS avg_humidity,
    reading_count
FROM sensor_data_hourly
WHERE hour > NOW() - INTERVAL '24 hours'
ORDER BY hour DESC, sensor_id
LIMIT 50;

Benefits of Continuous Aggregates

  • Faster queries: Pre-aggregated data means queries run in milliseconds instead of seconds
  • Incremental refresh: Only new/changed data is processed, not the entire dataset
  • Automatic updates: The refresh policy keeps your aggregates current without manual intervention
  • Real-time option: You can enable real-time aggregation to combine materialized and raw data

Try It Yourself

Compare the performance difference:

-- Query the raw hypertable (slower on large datasets)
\timing on
SELECT
    time_bucket('1 hour', time) AS hour,
    AVG(temperature) AS avg_temp
FROM sensor_data
WHERE time > NOW() - INTERVAL '60 days'
GROUP BY hour
ORDER BY hour DESC
LIMIT 24;

-- Query the continuous aggregate (much faster)
SELECT
    hour,
    avg_temp
FROM sensor_data_hourly
WHERE hour > NOW() - INTERVAL '60 days'
ORDER BY hour DESC
LIMIT 24;

Notice how the continuous aggregate query is significantly faster, especially as your dataset grows!

See more:

Examples

Learn TimescaleDB with complete, standalone examples using real-world datasets. Each example includes sample data and analytical queries.

Or try some of our workshops

Want TimescaleDB hosted and managed for you? Try Tiger Cloud

Tiger Cloud is the modern PostgreSQL data platform for all your applications. It enhances PostgreSQL to handle time series, events, real-time analytics, and vector search—all in a single database alongside transactional workloads. You get one system that handles live data ingestion, late and out-of-order updates, and low latency queries, with the performance, reliability, and scalability your app needs. Ideal for IoT, crypto, finance, SaaS, and a myriad other domains, Tiger Cloud allows you to build data-heavy, mission-critical apps while retaining the familiarity and reliability of PostgreSQL. See our whitepaper for a deep dive into Tiger Cloud's architecture and how it meets the needs of even the most demanding applications.

A Tiger Cloud service is a single optimized 100% PostgreSQL database instance that you use as is, or extend with capabilities specific to your business needs. The available capabilities are:

  • Time-series and analytics: PostgreSQL with TimescaleDB. The PostgreSQL you know and love, supercharged with functionality for storing and querying time-series data at scale for real-time analytics and other use cases. Get faster time-based queries with hypertables, continuous aggregates, and columnar storage. Save on storage with native compression, data retention policies, and bottomless data tiering to Amazon S3.
  • AI and vector: PostgreSQL with vector extensions. Use PostgreSQL as a vector database with purpose built extensions for building AI applications from start to scale. Get fast and accurate similarity search with the pgvector and pgvectorscale extensions. Create vector embeddings and perform LLM reasoning on your data with the pgai extension.
  • PostgreSQL: the trusted industry-standard RDBMS. Ideal for applications requiring strong data consistency, complex relationships, and advanced querying capabilities. Get ACID compliance, extensive SQL support, JSON handling, and extensibility through custom functions, data types, and extensions. All services include all the cloud tooling you'd expect for production use: automatic backups, high availability, read replicas, data forking, connection pooling, tiered storage, usage-based storage, and much more.

Check build status

Linux/macOSLinux i386WindowsCoverityCode CoverageOpenSSF
Build Status Linux/macOSBuild Status Linux i386Windows build statusCoverity Scan Build StatusCode CoverageOpenSSF Best Practices

Get involved

We welcome contributions to TimescaleDB! See Contributing and Code style guide for details.

Learn about Tiger Data

Tiger Data is the fastest PostgreSQL for transactional, analytical and agentic workloads. To learn more about the company and its products, visit tigerdata.com.

Troubleshooting

Docker container won't start

# Check if container is running
docker ps -a

# View container logs (use the appropriate container name)
# For one-line install:
docker logs timescaledb-ha-pg18-quickstart
# For manual Docker command:
docker logs timescaledb

# Stop and remove existing container
# For one-line install:
docker stop timescaledb-ha-pg18-quickstart && docker rm timescaledb-ha-pg18-quickstart
# For manual Docker command:
docker stop timescaledb && docker rm timescaledb

# Start fresh
# Option 1: Use the one-line install
curl -sL https://tsdb.co/start-local | sh
# Option 2: Use manual Docker command
docker run -d --name timescaledb -p 6543:5432 -e POSTGRES_PASSWORD=password timescale/timescaledb-ha:pg18

Can't connect with psql

  • Verify Docker container is running: docker ps
  • Check port 6543 isn't already in use: lsof -i :6543
  • Try using explicit host: psql -h 127.0.0.1 -p 6543 -U postgres

TimescaleDB extension not found

The timescale/timescaledb-ha:pg18 image has TimescaleDB pre-installed and pre-loaded. If you see errors, ensure you're using the correct image.

Clean Up

When you're done experimenting:

If you used the one-line install:

# Stop the container
docker stop timescaledb-ha-pg18-quickstart

# Remove the container
docker rm timescaledb-ha-pg18-quickstart

# Remove the persistent data volume
docker volume rm timescaledb_data

# (Optional) Remove the Docker image
docker rmi timescale/timescaledb-ha:pg18

If you used the manual Docker command:

# Stop the container
docker stop timescaledb

# Remove the container
docker rm timescaledb

# (Optional) Remove the Docker image
docker rmi timescale/timescaledb-ha:pg18

Note: If you created a named volume with the manual Docker command, you can remove it with docker volume rm <volume_name>.