ClickHouse can play the embedded game: clickhouse-local queries Parquet and CSV files from the command line with no server, and chDB, now developed inside ClickHouse Inc., packages the whole engine as an in-process Python library, a direct answer to DuckDB’s pip-install ergonomics. From the other side, DuckDB keeps growing upward: larger-than-memory execution, Iceberg and Delta readers, and DuckLake, a lakehouse format that keeps data in Parquet while putting the metadata in a real SQL database. The honest reading: ClickHouse versus DuckDB on a single node is closer to a coin flip on raw speed than either fan base admits, and ClickBench, ClickHouse’s own published benchmark suite, shows both in the top tier depending on query and hardware.
So the tiebreakers in the overlap zone are not speed. They are: who maintains it (a server needs an owner; a library needs a version bump), what the query concurrency looks like (one analyst vs a thousand dashboard sessions), and whether data arrives in batches or as a stream. A single beefy ClickHouse node serving Grafana panels around the clock is doing a job DuckDB structurally cannot; a DuckDB process inside a Lambda crunching one tenant’s Parquet on demand is a job where a ClickHouse server would be pure overhead.
The least-regret pattern we see: DuckDB for exploration, local pipelines, and anything embedded; ClickHouse when the same queries graduate to always-on, multi-user serving. The SQL dialects are close enough that the migration is mostly DDL, which is also why getting this choice wrong early is survivable.