Performance
Weekly benchmark
Run 2026-09-29 at commit 5924edb441fe: 43 ClickBench queries per reader, each reader a cold DuckDB with 4 / readers threads, on a 4-core GitHub runner. Shared hardware, so read it as a trend, not a score. Full history: history.jsonl.
| Readers | Queries/s | p50 | p95 | Geomean |
|---|---|---|---|---|
| 1 | 2.57 | 149 ms | 1333 ms | 149 ms |
| 2 | 2.7 | 313 ms | 1999 ms | 258 ms |
| 4 | 2.87 | 493 ms | 3589 ms | 431 ms |
Reference runs
Against an S3 gateway. Full ClickBench (100M rows), DuckDB 1.5.6, local kind. The same DuckLake read through DuckDB httpfs and a PostgreSQL-backed S3 gateway (pgvs3) was compared with pgvfs. Fresh DuckDB per query:
| S3 gateway | pgvfs | |
|---|---|---|
| Geomean | 430 ms | 371 ms (0.86×) |
| Warm geomean | 229 ms | 229 ms |
Short queries gain most, because the HTTP hop and HEAD revalidation are gone.
The heaviest string scans remain 2–7% slower. The run is from pgvs3 abcdb09,
before the split. It used identical data (checked by whole-table checksum),
the two stacks alternated run by run, and each figure is the median of 5.
Records: docs/results/vs-s3-gateway.jsonl.
Concurrent readers (just bench --parts 20 --readers 1,2,4,8,16). 20M
rows, PostgreSQL 18 and every DuckDB reader on one 16-core machine, each
reader with cores / readers threads, all 43 queries per reader from a cold
cache:
| Readers | Queries/s | p50 | p95 | geomean |
|---|---|---|---|---|
| 1 | 5.5 | 79 ms | 433 ms | 78 ms |
| 2 | 6.0 | 144 ms | 873 ms | 154 ms |
| 4 | 6.6 | 263 ms | 1.8 s | 266 ms |
| 8 | 6.3 | 621 ms | 3.8 s | 520 ms |
| 16 | 6.9 | 1.0 s | 6.5 s | 873 ms |
Throughput holds as readers are added, and latency follows each reader’s CPU share. On one machine the cores are the limit, not the storage layer. Readers on separate machines scale until PostgreSQL’s I/O or CPU saturates.