Resource costs
Shared price assumptions
One common price model for every engine. These are monthly resource equivalents, not measured cloud bills or cost per query. The first table weights CPU by measured work; the second keeps the always-on capacity reference. Each total-cost column uses its own lowest complete total as 1.00×. The separate CPU ratio uses the lowest positive observed CPU time. Neither is a query-speed ranking.
- CPU: $0.040 per vCPU-hour
- Memory: $0.0045 per GiB-hour
- Block storage: $0.080 per GiB-month
- S3-style object storage: $0.023 per GiB-month
Rounded generic assumptions, informed on 2026-09-25 by Fargate CPU/memory examples, EBS gp3 examples, and S3 Standard examples. For this model, one storage unit is 2³⁰ bytes (GiB).
Cost weighted by measured CPU work
Default scenario: 1,000 repetitions of each engine's recorded resource-sampling window per month, with its observed peak memory and stored data held for the month. CPU is charged only for measured busy time at the rates above. This shows how compute work changes the model even when every engine uses the same size machine.
Different historical sampling windows are not equal amounts of work. Query coverage and background activity differ, so these projections cannot establish an overall engine ranking.
CPU work cost = aggregate CPU seconds ÷ 3,600 × $0.04 × selected windows.
scenario total = CPU work cost + peak GiB × memory rate × selected hours
+ stored-footprint multiple × (block month + object month).
Why CPU and total ratios differ: the total also includes memory and storage. At low repetition counts, a month of peak memory can outweigh the CPU charge. The CPU ratio compares observed busy seconds only; the total ratio compares the selected scenario.
Increasing stored footprint projects retention cost while holding sampled CPU and peak memory fixed. That scaling has not been measured. Lower memory hours assume the working set can be released between active periods. These controls explore assumptions; they do not establish a winner on equivalent work or prove deployment feasibility.
| Engine | Run | CPU s / window | CPU / least busy | CPU / scenario | Memory / mo | Block / mo | Object / mo | Scenario total / mo | Total / cheapest |
|---|---|---|---|---|---|---|---|---|---|
| clickhouse | 2026-07-29 | 473.7 | 11.07× | $5.26 | $7.65 | $0.47 | $0.00 | $13.38 | 1.15× |
| clickhouse-s3 | 2026-07-29 | 560.3 | 13.09× | $6.23 | $8.74 | $0.00 | $0.50 | $15.46 | 1.33× |
| duckdb | 2026-07-29 | 753.8 | 17.61× | $8.38 | $5.32 | $0.14 | $0.00 | $13.84 | 1.19× |
| duckdb-s3 | 2026-07-29 | 716.7 | 16.75× | $7.96 | $7.79 | $0.00 | $0.04 | $15.79 | 1.36× |
| elasticsearch | 2026-07-29 | 878.4 | 20.52× | $9.76 | $107.98 | $1.67 | $0.00 | $119.41 | 10.26× |
| quickwit | 2026-09-01 | 42.8 | 1.00× | $0.48 | $10.77 | $0.00 | $0.39 | $11.64 | 1.00× |
| Siglake | 2026-09-02 | 56.7 | 1.32× | $0.63 | $19.35 | $0.00 | $0.05 | $20.03 | 1.72× |
| victorialogs | 2026-07-29 | 7,339.5 | 171.48× | $81.55 | $23.45 | $0.29 | $0.00 | $105.30 | 9.04× |
CPU seconds are summed across all cores by the node sampler, including background work; they are not wall-clock seconds and are not multiplied by core count again. Each run's observation is counted once, even though it is repeated on every query record. Sampling can include warmups, core and edge suites, and other work within the runner's window. Historical windows, repetition counts, supported queries and dates differ: these totals are illustrative resource equivalents, not equal-work cost-per-query rankings. A shorter or incomplete workload can look cheaper. See methodology and the query coverage and caveats before comparing.
This scenario assumes CPU can be billed or shared in exact proportion to busy time; an always-on VM still incurs the capacity cost below. By default it retains peak memory for 730 hours and storage for a month, excludes idle CPU, and does not prove this workload fits in a month or that any engine can be deployed at this price. Changing repetitions scales only CPU: 100 repetitions costs one tenth of the displayed CPU component; memory and storage stay fixed.
Always-on capacity reference
monthly equivalent = cores × 730 × $0.04 + peak GiB × 730 × $0.0045
+ block GiB × $0.08 + object GiB × $0.023.
The relative column is normalized within this table, not against the workload
scenario above. It is not a performance or capability ranking.
| Engine | Run | CPU / mo | Memory / mo | Block / mo | Object / mo | Total / mo | Relative |
|---|---|---|---|---|---|---|---|
| clickhouse | 2026-07-29 | $467.20 | $7.65 | $0.47 | $0.00 | $475.32 | 1.01× |
| clickhouse-s3 | 2026-07-29 | $467.20 | $8.74 | $0.00 | $0.50 | $476.44 | 1.01× |
| duckdb | 2026-07-29 | $467.20 | $5.32 | $0.14 | $0.00 | $472.66 | 1.00× |
| duckdb-s3 | 2026-07-29 | $467.20 | $7.79 | $0.00 | $0.04 | $475.03 | 1.01× |
| elasticsearch | 2026-07-29 | $467.20 | $107.98 | $1.67 | $0.00 | $576.85 | 1.22× |
| quickwit | 2026-09-01 | $467.20 | $10.77 | $0.00 | $0.39 | $478.37 | 1.01× |
| Siglake | 2026-09-02 | $467.20 | $19.35 | $0.00 | $0.05 | $486.60 | 1.03× |
| victorialogs | 2026-07-29 | $467.20 | $23.45 | $0.29 | $0.00 | $490.95 | 1.04× |
Uses recorded host cores, peak node memory and stored bytes from the same run as each engine's board column. Memory is peak usage, not allocated RAM; storage is occupied bytes, not provisioned volume size. This hybrid model does not establish a deployable instance size or equivalent throughput. It excludes spare capacity, replication, object requests, network transfer, extra IOPS, catalog services and software fees. The workload scenario replaces this CPU capacity charge; the two CPU charges are never added together. Missing inputs remain unassessed. Different rounds and unsupported queries limit comparisons.
Measured resource footprint
Measured on the same quiesced state as the latencies, in the same run as the engine's column on the results board (the run column names it). Block bytes must sit on a provisioned volume, sized in advance and paid for whether queried or not; object bytes live in S3 and are paid for as used. Peak memory here is node usage, not an engine-only allocation or a proven instance sizing requirement.
| engine | run | version | storage | block bytes | object bytes | vs raw | peak mem | CPU / sampling window |
|---|---|---|---|---|---|---|---|---|
| clickhouse | 2026-07-29 | — | block | 5.82 GiB | 0 | 18.9% | 2.3 GiB | 474 s |
| clickhouse-s3 | 2026-07-29 | — | object | 0 | 21.72 GiB | 70.7% | 2.7 GiB | 560 s |
| duckdb | 2026-07-29 | — | block | 1.73 GiB | 0 | 5.6% | 1.6 GiB | 754 s |
| duckdb-s3 | 2026-07-29 | — | object | 0 | 1.73 GiB | 5.6% | 2.4 GiB | 717 s |
| elasticsearch | 2026-07-29 | — | block | 20.87 GiB | 0 | 67.9% | 32.9 GiB | 878 s |
| quickwit | 2026-09-01 | — | object | 0 | 17.10 GiB | 55.6% | 3.3 GiB | 43 s |
| Siglake | 2026-09-02 | — | object | 0 | 2.38 GiB | 7.8% | 5.9 GiB | 57 s |
| victorialogs | 2026-07-29 | — | block | 3.65 GiB | 0 | 11.9% | 7.1 GiB | 7340 s |
Two caveats worth reading before comparing cells. The
vanilla-Parquet baseline retains the fewest bytes because it carries no index of
any kind — it is the floor for “just files”, not a like-for-like
comparison with an engine that also serves search. And the two ClickHouse series
are measured by different methods: the block series sums active parts
(system.parts), while the S3 series sums the object-store prefix,
which also includes inactive parts still awaiting cleanup. The S3 figure is
therefore an upper bound and the two ClickHouse rows should not be compared with
each other.