Performance
Measured on the full HTTP path (authentication, inspection, policy, execution and serialization) on a 6-core machine:
| Scenario | Time |
|---|---|
SELECT 1 |
~0.7 ms |
| point lookup | ~0.9 ms |
| 1 million rows × 4 columns, CSV | ~570 ms |
| 1 million rows, JSON | ~580 ms |
| 1 million rows, Arrow | ~140 ms |
Iceberg on R2 with cache_ttl |
~8 ms (250–900 ms without) |
- Use
format: arrowfor large results. DuckDB converts whole vectors to Arrow without value-by-value conversion, and pyarrow, polars and DuckDB read the stream directly. - Set
cache_ttlon REST catalogs. On R2 it turns 273 ms into 8 ms at p50 and 3 into 338 requests per second. - Put
LIMITin the SQL for samples. The row limit stops reading, butORDER BY, aggregation and window functions compute everything first. - Give users quotas so heavy queries cannot starve everyone else; see Limits and fairness.
Where the fixed cost goes
Section titled “Where the fixed cost goes”For small queries, latency is dominated by DuckDB’s own fixed cost. About 0.25 ms comes from guarantees kept on purpose: a fresh connection per request and the inspection that feeds the policy.
Row filters and masks add 0.4–0.5 ms on a local point lookup and nothing measurable on aggregations; see Column masking.