We just moved all run logs and spans from PostgreSQL to @ClickHouseDB. Here's why this matters and what we learned migrating billions of OpenTelemetry events 🧵
11
16
215
Replies
PostgreSQL hit a wall with dynamic attribute search. Every OTEL span has different attributes, and creating indexes for every possible JSON path wasn't feasible. Filtering/grouping across runs became impossibly slow at scale.
1
0
5
ClickHouse's columnar storage changes everything. Instead of storing entire rows together, it stores each column separately. This means querying just `run_id` and `duration` only reads those columns from disk, not the entire event structure.
1
0
4
The compression gains are also pretty amazing. Similar log attributes compress extremely well when stored together column-wise. We use ZSTD with delta encoding for timestamps and specialized codecs for different data patterns.
1
0
3
Our schema uses some clever @ClickHouseDB features: - Bloom filters for exact ID lookups - Token-based full-text search on attributes - minmax indexes for duration queries - Native JSON type that preserves full OTEL structure
1
1
9
The `attributes_text` field is a materialized column. ClickHouse auto-generates this as `toJSONString(attributes)` on insert. It lets us do full-text search on the JSON structure using tokenbf_v1 indexes without storing it twice.
2
0
3
Partitioning by date is perfect for logs since most queries are time-range based. Combined with ORDER BY on (environment_id, timestamp, trace_id), queries that filter by environment and time range are lightning fast.
1
0
3
TTL is built into the table definition: `TTL toDateTime(expires_at) + INTERVAL 7 DAY`. ClickHouse automatically drops old partitions. No cron jobs, no manual cleanup, it just handles data retention natively.
1
0
4
We built a dual-store architecture during migration. Both PostgreSQL and ClickHouse implement the same `IEventRepository` interface, with feature flags controlling which store is active. This enabled zero-downtime migration and easy rollback.
1
0
4
ClickHouse gives us eventual consistency instead of ACID guarantees. For observability data, slight delays are acceptable in exchange for massive performance gains. You don't need perfect consistency to debug a failed task run.
1
0
4
Materialized views unlock real-time usage metrics without expensive on-the-fly aggregations. They automatically maintain pre-aggregated stats as events are inserted.
1
0
4
The hardest parts? Unicode handling (unpaired surrogate pairs crash ClickHouse inserts), async insertions for write throughput, and maintaining nanosecond timestamp precision (DateTime64(9)) for accurate trace correlation.
1
0
3
Result: 50,000 logs per run in the dashboard (up from ~10k), instant filtering/aggregation, and we're now building log search on top of this foundation.
1
1
4
@triggerdotdev @ClickHouseDB This makes sense in general. To clarify, were you using generic Postgres? No extensions from @TigerDatabase or @neondatabase
1
0
1
@triggerdotdev @ClickHouseDB Perfect I need to do something similar soon and will steal your schema
0
0
1
@triggerdotdev @ClickHouseDB The migration sounds solid. ClickHouse's performance for log data is a game changer, especially with large datasets. How's the learning curve with those specialized features?
0
0
0
@triggerdotdev @ClickHouseDB Interesting to see the shift from PostgreSQL to ClickHouse for logs.
0
0
0