Every benchmark comparing ClickHouse and TimescaleDB tells the same story: ClickHouse wins the aggregation race, usually by 3-10x on complex queries over billions of rows, with compression ratios to match. The benchmarks are right. And yet teams keep choosing TimescaleDB, and most of them are right too. That tension is the whole comparison, and it resolves once you stop asking "which database is faster" and start asking a different question: is your time-series data an extension of your relational data, or a workload of its own?
TimescaleDB is a PostgreSQL extension that turns ordinary tables into automatically partitioned hypertables and adds a hybrid row-columnar storage engine, so time-series queries get columnar speed while everything remains a real Postgres database with joins, transactions, and the entire Postgres ecosystem. ClickHouse is a standalone columnar OLAP database built around the MergeTree storage engine, designed to ingest millions of rows per second and scan billions in sub-second time. One extends the database you already run. The other is a second engine you operate because the workload outgrew the first.
Two Philosophies, and a Rebrand That Confirms Them
The clearest evidence of where each product's center of gravity sits came from the vendors themselves. In June 2025, Timescale Inc. renamed itself TigerData and repositioned from "the time-series database" to "modern PostgreSQL for analytics and AI." That wasn't a retreat from time-series - the extension is still called TimescaleDB - but it was an admission that the product's real value proposition was never "fastest time-series engine." It was "you don't have to leave Postgres."
ClickHouse went the other direction and doubled down on being the destination. ClickHouse, Inc. now ships a CDC pipeline specifically for replicating TimescaleDB into ClickHouse, which tells you two things at once: enough teams outgrow TimescaleDB for this to be a product, and the graduation path is common enough to be paved. Neither fact means TimescaleDB failed those teams. A database you run for three years inside infrastructure you already understand, then migrate away from at a scale most projects never reach, has done its job.
Hypercore vs MergeTree: What Actually Happens on Disk
TimescaleDB's storage engine is now called Hypercore, a hybrid design where new data lands in a row-oriented store for fast inserts and updates, then converts automatically to a compressed columnstore as it ages. TigerData's docs report chunk-size reductions of 90-98% after conversion, and the engine keeps full ACID semantics across both stores - you can UPDATE a row that's already in the columnstore and Postgres MVCC still holds. The catch is that all of this runs inside the Postgres process model: one writer node, shared buffers, WAL, autovacuum. The columnar jacket doesn't change the body underneath.
ClickHouse's MergeTree engine (we've covered its internals before) stores every column separately, sorted by a primary key you choose, compressed with per-column codecs like Delta and ZSTD. There's no row-store stage, no MVCC overhead, and vectorized execution processes columns in batches. That's where the benchmark gap comes from - recent independent tests put ClickHouse at 15-30x compression on time-series data versus 10-15x for TimescaleDB, and ingestion throughput in the millions of rows per second where TimescaleDB typically sustains 100K-500K. These aren't tuning artifacts. They follow from ClickHouse refusing, by design, most of the guarantees Postgres provides.
| TimescaleDB (TigerData) | ClickHouse | |
|---|---|---|
| Architecture | PostgreSQL extension | Standalone columnar DBMS |
| Storage | Hypercore: rowstore then columnstore | MergeTree: columnar from insert |
| Compression | 90-98% chunk reduction (vendor docs) | 15-30x typical on time-series |
| Sustained ingestion | ~100K-500K rows/sec per node | Millions of rows/sec per node |
| UPDATE/DELETE | Full ACID, standard SQL | Lightweight updates (beta since 25.8), classic mutations otherwise |
| Joins with business data | Native, same database | Cross-database, or replicate tables in |
| Pre-aggregation | Continuous aggregates (incremental, transactional) | Materialized views (insert-triggered) |
| Ecosystem | Everything that speaks Postgres | ClickHouse-native drivers and integrations |
| Operational surface | Your existing Postgres, plus compression policies | A second distributed system (Keeper, replicas, merges) |
The Queries That Decide It
Both databases speak SQL, so the syntax gap that dominated our ClickHouse vs Elasticsearch comparison doesn't exist here. What differs is which queries are cheap. This TimescaleDB query is the kind ClickHouse can't match without extra plumbing:
SELECT c.plan, time_bucket('1 hour', m.time) AS hour,
avg(m.cpu_usage) AS avg_cpu
FROM metrics m
JOIN customers c ON c.id = m.customer_id
WHERE m.time > now() - interval '24 hours'
AND c.plan = 'enterprise'
GROUP BY c.plan, hour;
The join against customers - a live transactional table, updated by the application, in the same database - is free. In ClickHouse you'd replicate the customers table in, keep it fresh, and handle the fact that joins have historically been ClickHouse's weakest area. Meanwhile the inverse query shape - a full-history aggregation across tens of billions of rows, high cardinality, arbitrary time range - is where TimescaleDB hits the ceiling of the Postgres executor and ClickHouse returns in under a second.
Mutations tell the same story in reverse. TimescaleDB gives you standard UPDATE and DELETE with full transactional semantics, even on compressed data. ClickHouse spent years treating mutations as heavyweight background rewrites; the new lightweight UPDATE statement (experimental in 25.7, beta and on by default since 25.8) writes small patch parts instead and is up to 1,000x faster for point updates - but ClickHouse's own guidance still targets updates touching a small fraction of a table. If your workload corrects, backfills, or upserts routinely, that difference compounds daily.
What Each One Makes Painful
TimescaleDB's pains are Postgres pains, amplified by volume. A single writer node caps ingestion. Autovacuum still runs, and on high-churn hypertables it needs the same attention any busy Postgres does. Compression policies, chunk intervals, and continuous aggregate refresh schedules are new tuning surfaces that quietly determine whether you get the advertised ratios. And when a dashboard slows down, the diagnosis runs through the standard Postgres toolkit - pg_stat_statements, EXPLAIN, lock inspection - which is either a feature (your team knows it) or a limitation (the tools weren't built for columnstore internals).
ClickHouse's pains are the pains of operating a second distributed system. Replication runs through Keeper. Background merges compete with queries for CPU and disk, and a mistuned partitioning scheme shows up as mysterious CPU and memory spikes weeks later. There's no transactional consistency between your ClickHouse cluster and your application database - every pipeline feeding it is a place where data can drift, duplicate, or lag. None of this is exotic to teams who run distributed infrastructure. All of it is new to teams whose entire data platform was, until now, one Postgres instance.
The Bottom Line
If your time-series data lives inside an application that's already on Postgres - metrics joined with customers, sensor readings joined with devices, events joined with accounts - and volumes measure in millions to low billions of rows, TimescaleDB is the right answer, and the boring one: one system, real joins, real updates, one operational model. If the workload is a firehose measured in billions of rows and your queries are wide scans and aggregations detached from transactional data, ClickHouse isn't just faster - it's a different class of tool, and stretching Postgres to be that is how you end up doing capacity planning at 3am.
Key takeaways:
- The deciding variable is data gravity, not query speed: time-series that joins with relational data favors TimescaleDB; standalone analytical firehoses favor ClickHouse.
- ClickHouse wins raw numbers - roughly 3-10x on large aggregations, 15-30x compression, millions of rows/sec ingestion - because it drops the ACID and MVCC guarantees Postgres keeps.
- TimescaleDB's Hypercore closes more of the gap than old comparisons suggest, with 90-98% chunk compression and columnar reads, while keeping standard SQL mutations.
- The "start with TimescaleDB, graduate to ClickHouse" path is real and now product-supported via CDC replication; picking TimescaleDB first is not a mistake you'll pay to undo, it's usually the cheapest way to find out if you'll ever need ClickHouse.
- Whichever you choose, the failure mode isn't picking the wrong engine - it's running the right one blind. Both fail in ways that look like "it's slow" until you can see merges, vacuum, and query patterns from the inside.