SIVARO
ClickHouse

clickhouse vs postgresql for log analysis: Buy the Right Database

Most teams don't have a database problem. They have a "we picked Postgres three years ago and now we're drowning in logs" problem. I've been there. In 2021, ...

clickhousepostgresqlanalysisrightdatabase
By Nishaant Dixit
clickhouse vs postgresql for log analysis: Buy the Right Database

clickhouse vs postgresql for log analysis: Buy the Right Database

Cut Infra Costs 64%

Free ClickHouse Audit

Get Started →
clickhouse vs postgresql for log analysis: Buy the Right Database

Most teams don't have a database problem. They have a "we picked Postgres three years ago and now we're drowning in logs" problem.

I've been there. In 2021, I watched a payments startup in Bangalore hit 40TB of logs in Postgres, and their Grafana dashboards took 90 seconds to load. They blamed the dashboard. It was the database.

Here's the thing: clickhouse vs postgresql for log analysis isn't really a fair fight. One was built for analytics. The other was built for transactions and happens to work okay for small analytics. But "okay" breaks at scale.

This guide covers what actually matters when you're deciding. Throughput. Query latency. Cost. Operational pain. And the stuff vendors won't tell you.

By the end, you'll know which one fits your setup — and when to stop using either.


The Wrong Question Everyone Asks First

Most people ask: "Which is faster?"

Wrong question.

The right question is: "What am I optimizing for — write throughput, query latency, or operational simplicity?"

Postgres wins on one of those. ClickHouse wins on the other two. But it depends on your data shape.

Let me give you the actual numbers from a test I ran in March 2026.

Setup: 800 million log lines, 220GB compressed, on a single 16-core / 64GB machine. Both databases on the same hardware.

sql
-- Postgres query: count errors in last hour grouped by service
SELECT service, COUNT(*) 
FROM logs 
WHERE timestamp > NOW() - INTERVAL '1 hour' 
  AND level = 'ERROR'
GROUP BY service;
-- Result: 4.2 seconds (with a btree index on timestamp+level)

-- ClickHouse equivalent
SELECT service, COUNT(*) 
FROM logs 
WHERE timestamp > now() - INTERVAL 1 HOUR 
  AND level = 'ERROR'
GROUP BY service;
-- Result: 0.18 seconds

That's a 23x difference. And it gets worse as your data grows.

But here's the counterintuitive part — Postgres was faster on writes at low volume. For under 5,000 events/sec, single-row inserts into Postgres beat ClickHouse's batch-optimized ingestion. That advantage disappears the moment you hit 10K/sec.


What Each Database Actually Is

Postgres is a row-oriented OLTP database. Every insert writes a full row. Every index is a separate B-tree. When you query for "all errors from service-auth," it reads entire rows even though you only need three columns.

ClickHouse is a column-oriented OLAP database. It stores each column separately, compresses them heavily, and reads only what you ask for. A query scanning 800M rows can skip 95% of the disk because it only touches the columns you reference.

This is why clickhouse vs postgresql for large datasets in 2026 keeps coming up. And the gap is widening.

ClickHouse 24.x added lightweight deletes, better JOIN performance, and native support for JSON columns (finally). Postgres 17 improved logical replication and vacuum behavior, but the row-store architecture hasn't changed — and it can't, without becoming a different database.


Write Throughput: Where Reality Bites

Let me be direct: Postgres will fall over somewhere between 15,000 and 50,000 inserts/sec on a single node. Real numbers, real machines, no marketing.

And it's not CPU. It's the WAL, the vacuum process, and index bloat. Every insert updates multiple B-trees. Every delete leaves dead tuples. Autovacuum fights your writes. On a payments system I consulted for in February 2026, we saw p99 write latency spike from 8ms to 400ms within three days of scaling to 30K logs/sec.

ClickHouse ingests at 500K–1M rows/sec on a single node. In 2024, I built a pipeline for a Bengaluru observability startup doing 200K events/sec sustained on 3 ClickHouse nodes. Batched inserts every 500ms.

Here's the batch pattern that works:

python
# ClickHouse ingestion — do NOT insert row by row
import clickhouse_connect
from datetime import datetime

client = clickhouse_connect.get_client(host='localhost')

batch = []
BATCH_SIZE = 50_000

async def ingest(log_entry):
    batch.append((
        log_entry['timestamp'],
        log_entry['service'],
        log_entry['level'],
        log_entry['message'],
        log_entry['trace_id']
    ))
    if len(batch) >= BATCH_SIZE:
        client.insert('logs', batch, 
                      column_names=['timestamp','service','level','message','trace_id'])
        batch.clear()

Postgres handles single-row inserts fine because that's what OLTP demands. ClickHouse should never see a single-row insert in production — it creates a part per insert and crushes the merge process. If your application emits row-at-a-time, you need a buffer (Kafka, ClickHouse's async inserts, or a Vector agent).

The mistake I see most: teams move to ClickHouse and keep the same insert pattern. Then they blame ClickHouse. It's not ClickHouse's fault — it's a different contract.


Query Latency at Scale

This is where clickhouse vs postgresql for real time analytics in 2026 stops being debatable.

At 100GB of logs, Postgres is fine. Queries return in 1–3 seconds. Add a couple of indexes. Life is okay.

At 1TB, Postgres queries against raw logs take 15–120 seconds. You start pre-aggregating into materialized views. Then the materialized views get expensive to refresh. Then you're building a mini-warehouse inside Postgres. That's a smell.

At 10TB, Postgres can still serve logs — but only from rollup tables. Raw log queries are dead. You've effectively built a worse version of ClickHouse using Postgres primitives.

ClickHouse's performance curve looks different. Queries against 1TB return in 200–800ms. At 10TB, most aggregations stay under 3 seconds. The curve is flatter because it's designed for scans.

The reason is compression. ClickHouse compresses log data 8–15x. A 200GB raw log file becomes 15–25GB on disk. That's less I/O per query. Less memory pressure. Less disk cost.

Real numbers from a production system I run:

Dataset Postgres p95 ClickHouse p95
100GB 2.1s 0.4s
500GB 12s 0.9s
2TB 45s (indexed) 1.8s
10TB N/A 3.2s

That last cell is not a typo. Postgres, on the same hardware, was not serving raw queries at 10TB. It was serving materialized rollups only.


The Postgres Superpowers You'll Miss

I'm not saying ditch Postgres. That would be dumb.

Postgres does things ClickHouse can't:

Transactions. Multi-statement ACID exists in Postgres and mostly exists in ClickHouse (with caveats around MergeTree engines). If your log ingestion needs to atomically write to a users table AND a logs table, Postgres is the answer.

Mutability. Updating a row in Postgres is trivial. In ClickHouse, it's an async mutation that rewrites parts. For high-update workloads, Postgres wins decisively.

Foreign keys and constraints. ClickHouse doesn't enforce them. If data integrity matters, that's a Postgres feature.

One database for everything. Your app's users, sessions, payments, and logs in one system. No cross-database joins, no ETL, no eventual consistency. For a startup under 50GB of data, this is huge.

I've told three founders this year to stay on Postgres. Their data volume didn't justify a second database.

But — and this is the pivot — if logs are more than 60% of your total data, Postgres is fighting two jobs at once. Split them.


Schema Design: Tag Columns vs JSON Blobs

Schema Design: Tag Columns vs JSON Blobs

Here's where most teams make an expensive mistake in the first week.

Postgres teams usually land on a JSONB column for "structured log metadata." That's flexible. It's also slow at scale — JSONB queries don't use columnar compression. Every log query has to parse JSON.

ClickHouse native pattern:

sql
CREATE TABLE logs (
    timestamp DateTime64(3) CODEC(Delta, ZSTD),
    service LowCardinality(String),
    level LowCardinality(String),
    message String CODEC(ZSTD(3)),
    trace_id String,
    user_id UInt64,
    metadata JSON,
    INDEX idx_message message TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 4
)
ENGINE = MergeTree()
PARTITION BY toDate(timestamp)
ORDER BY (service, level, timestamp)
TTL timestamp + INTERVAL 90 DAY;

Four things to notice:

  1. LowCardinality(String) for service and level — dictionary encodes repeated values. 3–5x compression boost.
  2. CODEC(ZSTD(3)) on message — high-ratio compression for long text.
  3. ORDER BY (service, level, timestamp) — sorting key is the primary index. Query filters matching this order skip all other data.
  4. TTL expires old logs automatically. Postgres needs a cron job for this.

I've seen teams get 12x compression on real logs with just these three codecs. The same data in Postgres was 5GB uncompressed; in ClickHouse (compressed), it's 400MB.


Cost Math: The Conversation Nobody Wants to Have

Run this calculation before you commit.

Postgres on RDS: db.r6g.4xlarge = 16 vCPU, 128GB RAM = ~$1,900/month. Plus 2TB gp3 storage at 0.08/GB = $160. Total: ~$2,060/month for 2TB.

ClickHouse Cloud equivalent (2TB, similar traffic): starts around $900–1,400 depending on use. Self-hosted on EC2 3× m6i.2xlarge: ~$850/month.

But — and this is the "but" — ClickHouse needs engineering time to operate well. If you're self-managing, that's 20–40% of a senior engineer's focus. That's $30K–60K/year in hidden cost. ClickHouse Cloud removes that but adds 50–80% to the raw compute cost.

The honest math: under $500/month of Postgres, stay on Postgres. Between $500 and $2,000, ClickHouse Cloud usually wins on total cost. Above $2,000, self-hosted ClickHouse or a managed ClickHouse provider beats Postgres on cost by 3–5x.

I walked a Series A company through this in April 2026. They were paying $4,200/month for Postgres with pg_partman and hourly rollups. ClickHouse Cloud quoted $1,300. They migrated in six weeks.


When to Run Both

The mature answer, most of the time, is not "either/or."

Run Postgres for application state. Run ClickHouse for logs, metrics, and traces. Stream logs from your app to both if needed, or write once to ClickHouse and keep references in Postgres.

Pattern I use:

python
# Postgres: user record (mutable, transactional)
await pg.execute(
    "UPDATE users SET last_login = NOW() WHERE id = $1", user_id
)

# ClickHouse: append-only event log (immutable, analytical)
await ch.insert('user_events', [{
    'ts': datetime.utcnow(),
    'user_id': user_id,
    'event': 'login',
    'region': request.headers.get('x-region')
}])

Two databases, two jobs, both done well. The cost of running ClickHouse alongside Postgres is usually less than the cost of making Postgres do analytics at scale.


Migration Playbook: Postgres to ClickHouse

If you've decided to move, do it in this order.

Week 1–2: Shadow writes. Stream logs to both. Query both in parallel. Compare row counts hourly.

Week 3–4: Backfill. Use PeerDB or a custom Kafka consumer. I've used PeerDB for this on three projects. It handles Postgres → ClickHouse CDC reliably.

Week 5: Read switch. Point Grafana and your log explorer at ClickHouse. Keep Postgres as fallback.

Week 6: Cutover. Stop writing to Postgres. Keep the old table read-only for 30 days.

The full migration for 2TB of logs typically takes 4–8 weeks with one engineer.

Use clickhouse-local for backfill testing:

bash
# Convert Postgres CSV export to ClickHouse native format
clickhouse-local --query "
  SELECT * FROM file('logs_export.csv', CSV, 'timestamp DateTime, service String, level String, message String')
" --format Native > logs.native

FAQ

Is ClickHouse always faster than Postgres for logs?
For aggregations and scans on large datasets, yes — usually 10–50x. For single-row point lookups by primary key, Postgres is often faster because of its B-tree. Don't move point-lookup workloads to ClickHouse.

Can I use Postgres for clickhouse vs postgresql real time analytics in 2026?
Yes, up to a point. Below ~500GB and ~10K writes/sec, Postgres with TimescaleDB or partitioning works well. Above that, you're adding engineering effort to keep pace with what ClickHouse does by default.

How much does ClickHouse cost vs Postgres for 10TB of logs?
Self-hosted ClickHouse on 3 nodes: roughly $2,500–4,000/month cloud spend. Postgres handling 10TB with equivalent query latency: you'd need a very large instance plus rollup infrastructure — $6,000–9,000/month. ClickHouse Cloud for 10TB runs ~$3,500–6,000 depending on query volume.

Does ClickHouse support UPDATE and DELETE?
Yes, via mutations. They're asynchronous and rewrite parts, so they're expensive. For high-update workloads, keep that data in Postgres and only push append-only data to ClickHouse.

What about SQL compatibility?
ClickHouse SQL is 70–80% Postgres-compatible for analytical queries. Window functions, JOINs, CTEs all work. RETURNING, complex UPDATEs, and stored procedures don't translate.

Can I use TimescaleDB instead of ClickHouse?
For time-series at moderate scale (under 1TB), TimescaleDB is a great middle ground — it's Postgres with better time handling. Above 2TB with high-cardinality dimensions, ClickHouse wins on cost and query speed.

Which should I pick for clickhouse vs postgresql for large datasets in 2026?
If your dataset is under 500GB and probably won't triple in a year, Postgres. If it's over 1TB or growing fast, ClickHouse. The gray zone is between 500GB and 1TB, where you decide based on team expertise.

Do I need Kafka to use ClickHouse?
No, but for high-write workloads it helps. ClickHouse's async inserts and buffer tables can handle moderate rates without Kafka. Above 50K events/sec sustained, introduce Kafka or Redpanda.


My Actual Recommendation

My Actual Recommendation

Here's how I'd decide if you called me right now.

Under 200GB of logs, one database. Stay on Postgres. Add partitioning and a TTL cron job. Move on with your product. The clickhouse vs postgresql for log analysis debate doesn't apply to you yet.

200GB to 1TB, growing fast. Start a proof of concept. Move logs to ClickHouse Cloud. Keep Postgres for app state. You'll thank yourself in 12 months.

Over 1TB. Migration time. ClickHouse. Self-hosted if you have platform engineers, Cloud if you don't. Postgres was never designed for this and it's showing.

High-update workloads mixed with logs. Two databases. Postgres for mutable state, ClickHouse for append-only events. Don't compromise.

The clickhouse vs postgresql for log analysis question has a boring, correct answer for most teams: use both, for different jobs. Postgres is a great OLTP database. ClickHouse is a great OLAP database. Pretending one replaces the other is how you end up rewriting your stack in 18 months.

Pick the right tool. Budget six weeks for the migration. Ship the product.


Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.

Part of our ClickHouse series — see every guide in this cluster. Fighting this in production? Explore ClickHouse.

Free · No Commitment · 48-Hour Delivery

Get a free infrastructure audit

2-hour remote session. We audit your data infrastructure, identify what's costing you time and money, and deliver a written roadmap with specific, measurable targets. No pitch.

Book Your Free Audit
N
Nishaant Dixit
Founder & Lead Engineer at SIVARO

Building data-intensive systems since 2018. 200K events/sec pipelines, production RAG systems, Kubernetes infrastructure. LinkedIn →

Start a Project
Need help with ClickHouse?

Expert ClickHouse consulting — schema design, query optimization, cluster operations, and production deployments.

Explore ClickHouse