PostHog: DuckDB vs ClickHouse — why we use both
PostHog’s engineering blog on running both DuckDB and ClickHouse in production — the independent practitioner anchor of this spoke (synthesis), and the counterweight to the vendor tinybird-clickhouse-vs-duckdb.
The architecture
- clickhouse powers PostHog’s core product analytics — “funnels, trends, retention, and paths over billions of events” — via streaming append-only ingest and insert-time materialized views.
- duckdb powers their managed data-warehouse product, letting customers store/transform/query all their data (not just PostHog events). Wrapped in Duckgres (a Postgres-compatible server) for BI-tool + dbt compatibility, with each process pointed at independent storage (DuckLake + a Postgres catalog) to decouple compute from storage.
- They also run Postgres for application state — three stores, each for its job.
Why both, not one
ClickHouse’s self-managed deployment “had constraints that meant it simply would not work for data warehousing for all of our customers,” and the warehouse needed to scale independently of production analytics. DuckDB’s lightweight, embeddable nature fit per-tenant warehousing; ClickHouse’s proven horizontal scaling fit their own billions-of-events streams.
Trade-offs they name
Scaling (ClickHouse horizontal+vertical vs DuckDB vertical-only), deployment (server/client-server vs embedded/file-based), ingestion (continuous streaming MergeTree vs batch loading), and operational complexity (MergeTree tuning + ZooKeeper-managed replicas vs minimal setup).
Tier
T2 — independent first-party engineering experience. Credible because it names both tools’ limits, describes the problem that forced DuckDB in, and builds custom infra (Duckgres) around DuckDB’s constraints rather than engineering toward any one vendor. The load-bearing source for the spoke’s “which engine for which layer” thesis.
Related
clickhouse · duckdb · analytical-databases · tinybird-clickhouse-vs-duckdb · synthesis