Transparent, reproducible benchmark methodology and results. We believe in honest performance claims backed by rigorous testing.
Every performance claim we make is backed by open-source benchmark code that anyone can run. We believe that database benchmarks should be transparent in methodology, reproducible in any environment, and fair to all systems under comparison. This document describes exactly how we conduct our benchmarks -- from hardware configuration to statistical analysis -- so you can evaluate our results with full confidence and reproduce them yourself.
We follow three principles:
We run four distinct types of benchmarks, each designed to measure a different dimension of database performance.
Measure the raw cost of individual operations in an embedded deployment, with no network overhead. These isolate the storage engine and query executor.
| Operation | What It Measures |
|---|---|
| Point lookup (PK) | ART index traversal + MVCC read |
| Single-row INSERT | Write path + WAL + commit |
| Range scan (100 rows) | Sequential read throughput |
| Aggregate (COUNT/SUM) | Full-table scan + computation |
| Index creation | Bulk ART construction |
Measure how throughput scales as concurrent clients increase, using pgbench over the PostgreSQL wire protocol.
| Concurrency Level | Purpose |
|---|---|
| 10 clients | Baseline contention-free performance |
| 50 clients | Moderate concurrency |
| 100 clients | Production-typical load |
| 200 clients | High-concurrency stress |
| 500 clients | Connection pool saturation |
| 1000 clients | Extreme concurrency |
Head-to-head comparison across 35 SQL query categories. Both engines receive identical schemas, identical data, and identical queries. The embedded Rust-native comparison eliminates network variables.
| # | Category | # | Category |
|---|---|---|---|
| 1 | CREATE TABLE | 19 | LEFT JOIN |
| 2 | CREATE INDEX | 20 | Multi-table JOIN (4 tables) |
| 3 | ALTER TABLE | 21 | Scalar subquery |
| 4 | DROP TABLE | 22 | EXISTS subquery |
| 5 | CREATE/DROP VIEW | 23 | IN subquery |
| 6 | REFRESH Materialized View | 24 | Common Table Expression (CTE) |
| 7 | TRUNCATE | 25 | Recursive CTE |
| 8 | INSERT (single-row) | 26 | Window functions |
| 9 | INSERT (multi-row) | 27 | UNION |
| 10 | INSERT...SELECT | 28 | DISTINCT |
| 11 | UPDATE (point) | 29 | ORDER BY + LIMIT |
| 12 | DELETE (point) | 30 | CASE expressions |
| 13 | UPSERT (ON CONFLICT) | 31 | JSON filter |
| 14 | UPDATE with subquery | 32 | LIKE / BETWEEN / IN |
| 15 | Point lookup (PK) | 33 | Transaction control |
| 16 | Full scan + filter | 34 | Prepared statements |
| 17 | Aggregation | 35 | SET / SHOW / RESET |
| 18 | INNER JOIN |
Compare HeliosDB + HeliosProxy against PostgreSQL + PgBouncer in Docker containers, using pgbench as the standard load generator. This tests real-world deployment conditions: network overhead, connection pooling, and container resource constraints.
All published benchmarks are run on the following reference hardware unless otherwise noted:
| Component | Specification |
|---|---|
| CPU | 8-core (x86_64) |
| Memory | 32 GB DDR4 |
| Storage | NVMe SSD (sequential read >3 GB/s) |
| OS | Linux (kernel 5.14+) |
| Rust | stable (latest) |
| Docker | 24.x with Compose v2 |
Both database systems receive equal container resources to ensure a fair comparison:
# PostgreSQL container
deploy:
resources:
limits:
cpus: '2'
memory: 2G
# HeliosDB container
deploy:
resources:
limits:
cpus: '2'
memory: 2G
PostgreSQL receives production-recommended tuning. This favors PostgreSQL, since HeliosDB uses default configuration.
shared_buffers = 512MB
effective_cache_size = 2GB
work_mem = 64MB
max_connections = 500
HeliosDB runs with default out-of-the-box settings. No special tuning is applied. This demonstrates real-world performance for users who deploy without manual optimization.
Each benchmark follows the same execution protocol:
1. Schema creation (identical DDL for both systems)
2. Data population (identical rows, same cardinality)
3. Warmup phase: 30 seconds (queries run but not measured)
4. Measurement phase: 30 seconds (all metrics collected)
5. Cooldown and results aggregation
Both the warmup and measurement durations are configurable. Published results use 30-second windows unless stated otherwise.
| Benchmark Type | Tool | Rationale |
|---|---|---|
| Wire protocol (Docker) | pgbench (PostgreSQL 16) | Industry-standard OLTP benchmark tool |
| Embedded comparison | Rust-native harness | Eliminates network overhead; measures engine directly |
| Scalability | pgbench with varying -c flag | Standard concurrency scaling methodology |
Queries are designed to isolate specific operations:
-- Point lookup (PK index scan)
SELECT * FROM customers WHERE id = 42;
-- Range scan with filter
SELECT * FROM customers WHERE age BETWEEN 25 AND 35;
-- Aggregation
SELECT region, COUNT(*), AVG(age) FROM customers GROUP BY region;
-- INNER JOIN (2 tables)
SELECT c.name, o.order_id, o.total
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id
WHERE c.region = 'East';
-- Multi-table JOIN (4 tables)
SELECT c.name, o.order_id, p.name, oi.quantity
FROM customers c
JOIN orders o ON o.customer_id = c.id
JOIN order_items oi ON oi.order_id = o.order_id
JOIN products p ON p.product_id = oi.product_id
WHERE o.status = 'shipped';
-- Window function
SELECT name, age, region,
ROW_NUMBER() OVER (PARTITION BY region ORDER BY age DESC)
FROM customers;
-- Recursive CTE
WITH RECURSIVE tree AS (
SELECT cat_id, name, parent_id, 0 AS depth
FROM categories WHERE parent_id IS NULL
UNION ALL
SELECT c.cat_id, c.name, c.parent_id, t.depth + 1
FROM categories c JOIN tree t ON c.parent_id = t.cat_id
)
SELECT * FROM tree ORDER BY depth, cat_id;
-- EXISTS subquery
SELECT c.name FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id AND o.status = 'shipped'
);
-- LIKE / BETWEEN / IN
SELECT * FROM customers
WHERE name LIKE 'Customer_1%'
AND age BETWEEN 20 AND 50
AND region IN ('East', 'West');
Both systems are populated with identical data:
| Table | Rows | Description |
|---|---|---|
| customers | 200 | 7 columns including name, email, age, region, metadata |
| products | 50 | 5 columns including category, price, description |
| orders | 500 | 5 columns with FK to customers |
| order_items | 1,000 | 5 columns with FKs to orders and products |
| categories | 20 | Hierarchical (self-referencing parent_id) |
| Metric | Unit | Description |
|---|---|---|
| TPS | transactions/sec | Completed transactions per second during measurement window |
| P50 latency | microseconds | Median latency (50th percentile) |
| P95 latency | microseconds | 95th percentile latency |
| P99 latency | microseconds | 99th percentile latency |
| Metric | Formula | Description |
|---|---|---|
| Scaling factor | TPS(N threads) / TPS(1 thread) | How well throughput scales with concurrency |
| Scaling efficiency | Scaling factor / N | Percentage of ideal linear scaling |
| Comparison ratio | HeliosDB time / PostgreSQL time | Values < 1.0 mean HeliosDB is faster |
| Speedup | 1 / comparison ratio | e.g., ratio 0.15 = 6.9x speedup |
HeliosDB benchmarks also collect internal per-phase timing via the built-in tracing system:
| Phase | What It Measures |
|---|---|
| Parse | SQL text to AST (sqlparser-rs) |
| Plan | AST to logical plan |
| Optimize | Rule-based and cost-based optimization passes |
| Execute | Plan execution against storage engine |
Enable tracing with:
SET helios.trace_queries = on;
-- Run queries...
SHOW helios.trace_report;
A system "wins" a category only if it is more than 5% faster than the other system. Results within 5% are reported as comparable (within noise margin).
| Ratio Range | Verdict |
|---|---|
| < 0.95 | HeliosDB wins |
| 0.95 -- 1.05 | Comparable (within noise) |
| > 1.05 | PostgreSQL wins |
| Rule | Details |
|---|---|
| Same queries | Identical SQL text (adjusted only for syntax differences where necessary) |
| Same data | Identical row counts, identical values, same cardinality |
| Same hardware | Both run on the same machine (embedded) or same Docker host (wire protocol) |
| Warm caches | Both systems execute warmup queries before measurement begins |
| Index fairness | PostgreSQL uses B-tree indexes; HeliosDB uses ART indexes (each system's default) |
| Configuration | PostgreSQL gets production tuning (shared_buffers=512MB); HeliosDB uses defaults |
ratio = HeliosDB average time / PostgreSQL average time
| Ratio | Meaning |
|---|---|
| 0.14 | HeliosDB is 6.9x faster |
| 0.40 | HeliosDB is 2.5x faster |
| 1.00 | Identical performance |
| 1.20 | PostgreSQL is 1.2x faster |
PostgreSQL: B-tree index on primary keys (O(log n) lookup)
HeliosDB: ART index on primary keys (O(k) lookup, k = key length)
Both systems create indexes on the same columns. The index type reflects each system's default and strength.
HeliosDB comes in three editions, each optimized for different use cases. All are benchmarked against PostgreSQL 16 using the same 35-category suite.
Scoreboard: Lite wins 33 | PostgreSQL wins 2
Embedded benchmark, plan cache enabled, release mode. Dataset: 200 customers, 50 products, 500 orders, 1,000 items. March 2026.
| # | Category | HeliosDB | PostgreSQL 16 | Winner |
|---|---|---|---|---|
| 1 | CREATE TABLE | 100 us | 5.07 ms | HeliosDB (50.7x) |
| 2 | CREATE INDEX | 544 us | 2.43 ms | HeliosDB (4.5x) |
| 3 | ALTER TABLE | 61 us | 1.34 ms | HeliosDB (21.9x) |
| 4 | DROP TABLE | 24 us | 908 us | HeliosDB (37.8x) |
| 5 | CREATE/DROP VIEW | 85 us | 1.99 ms | HeliosDB (23.4x) |
| 6 | REFRESH MATVIEW | 3 us | 3.84 ms | HeliosDB (1,279x) |
| 7 | TRUNCATE | 180 us | 4.32 ms | HeliosDB (24.0x) |
| 8 | INSERT single | 32 us | 471 us | HeliosDB (14.7x) |
| 9 | INSERT multi-row | 146 us | 511 us | HeliosDB (3.5x) |
| 10 | INSERT..SELECT | 159 ms | 848 us | PostgreSQL (188x) |
| 11 | UPDATE point | 37 us | 1.18 ms | HeliosDB (31.8x) |
| 12 | DELETE point | 40 us | 1.10 ms | HeliosDB (27.5x) |
| 13 | UPSERT | 857 us | 1.18 ms | HeliosDB (1.4x) |
| 14 | UPDATE + subquery | 799 ms | 654 us | PostgreSQL (1,222x) |
| 15 | Point lookup (PK) | 44 us | 175 us | HeliosDB (4.0x) |
| 16 | Full scan + filter | 12 us | 219 us | HeliosDB (18.3x) |
| 17 | Aggregation | 5 us | 227 us | HeliosDB (45.4x) |
| 18 | INNER JOIN | 190 us | 254 us | HeliosDB (1.3x) |
| 19 | LEFT JOIN | 172 us | 266 us | HeliosDB (1.6x) |
| 20 | 4-table JOIN | 362 us | 728 us | HeliosDB (2.0x) |
| 21 | Scalar subquery | 9 us | 329 us | HeliosDB (36.6x) |
| 22 | EXISTS subquery | 10 us | 495 us | HeliosDB (49.5x) |
| 23 | IN subquery | 10 us | 414 us | HeliosDB (41.4x) |
| 24 | CTE | 27 us | 541 us | HeliosDB (20.0x) |
| 25 | Recursive CTE | 12 us | 362 us | HeliosDB (30.2x) |
| 26 | Window functions | 58 us | 419 us | HeliosDB (7.2x) |
| 27 | UNION | 10 us | 283 us | HeliosDB (28.3x) |
| 28 | DISTINCT | 3 us | 192 us | HeliosDB (64.0x) |
| 29 | ORDER BY + LIMIT | 105 us | 254 us | HeliosDB (2.4x) |
| 30 | CASE expressions | 17 us | 223 us | HeliosDB (13.1x) |
| 31 | LIKE/BETWEEN/IN | 14 us | 278 us | HeliosDB (19.9x) |
| 32 | String ops | 13 us | 229 us | HeliosDB (17.6x) |
| 33 | Transaction ctl | 29 us | 948 us | HeliosDB (32.7x) |
| 34 | Prepared stmts | 77 us | 497 us | HeliosDB (6.5x) |
| 35 | SET/SHOW/RESET | 11 us | 416 us | HeliosDB (37.8x) |
| Metric | Lite v3.6.0 | PostgreSQL 16 | Speedup |
|---|---|---|---|
| Aggregation (COUNT/SUM) | 5 us | 227 us | 45.4x faster |
| EXISTS subquery | 10 us | 495 us | 49.5x faster |
| DISTINCT | 3 us | 192 us | 64.0x faster |
| REFRESH MATVIEW | 3 us | 3.84 ms | 1,279x faster |
| CREATE TABLE | 100 us | 5.07 ms | 50.7x faster |
| Point lookup (PK) | 44 us | 175 us | 4.0x faster |
| Plan cache hit | 18 us | N/A | 129x vs cold |
| Category | Gap | Why |
|---|---|---|
| INSERT..SELECT | 188x | PostgreSQL's bulk COPY path is highly optimized for batch inserts from subqueries. HeliosDB evaluates the subquery row-by-row. |
| UPDATE + subquery | 1,222x | Correlated subquery in UPDATE re-evaluates per row. PostgreSQL materializes the subquery once. Known optimization target. |
| Clients | HeliosDB TPS | Scaling Factor | Efficiency |
|---|---|---|---|
| 10 | 242 | 1.0x | 100% |
| 50 | 1,209 | 5.0x | 100% |
| 100 | 2,419 | 10.0x | 100% |
| 200 | 4,825 | 19.9x | 100% |
| 500 | 11,775 | 48.7x | 97% |
| 1,000 | 20,491 | 84.7x | 85% |
HeliosDB demonstrates near-linear scaling up to 500 concurrent clients (97% efficiency) and maintains 85% efficiency at 1,000 clients.
Same 35 categories, same dataset, same PostgreSQL 16 baseline. This table compares all three editions side-by-side on shared categories.
| Category | Lite v3.6.0 | Nano v3.8.1 | PG 16 |
|---|---|---|---|
| Point lookup (PK) | 44 us | 3 us | 175 us |
| Aggregation | 5 us | <1 us | 227 us |
| Full scan + filter | 12 us | 20 us | 235 us |
| INNER JOIN | 190 us | 325 us | 254 us |
| CTE | 27 us | 16 us | 537 us |
| Window funcs | 58 us | 13 us | 401 us |
| INSERT single | 32 us | 213 us | 452 us |
| Transaction ctl | 29 us | 210 us | 948 us |
Lite excels at JOINs, DML, and broad SQL coverage (33/35 wins). Nano excels at point lookups, analytics, and cached queries (20/28 wins, 7 N/A). Full targets scale-out server workloads via wire protocol.
All benchmark code is open-source in the HeliosDB repository.
Requires a local PostgreSQL 16 instance for the comparison side:
# Start PostgreSQL 16 for comparison
docker run -d --name pg_bench_16 \
-e POSTGRES_USER=bench \
-e POSTGRES_PASSWORD=benchpass \
-e POSTGRES_DB=benchdb \
-p 25432:5432 \
postgres:16-alpine
# Run the 35-category comparison benchmark
cargo test --release --test pg_comparison_benchmark -- --nocapture --ignored
The benchmark will:
# Start the full benchmark environment
docker compose -f benchmarks/docker/docker-compose.benchmark.yml up -d
# Wait for all services to be healthy
docker compose -f benchmarks/docker/docker-compose.benchmark.yml ps
# Run benchmarks from the runner container
docker exec -it benchmark-runner bash /scripts/run-benchmarks.sh
# Start the scalability test environment
docker compose -f benchmarks/docker/docker-compose.scalability.yml up -d
# Run scalability sweep (10, 50, 100, 200, 500, 1000 clients)
docker exec -it benchmark-runner bash /scripts/scalability-benchmark.sh
The benchmark suite outputs a markdown table. Key columns:
| Column | Meaning |
|---|---|
HeliosDB | Average time per iteration for HeliosDB |
PostgreSQL | Average time per iteration for PostgreSQL |
Ratio | HeliosDB / PostgreSQL (< 1.0 = HeliosDB faster) |
Winner | Which system won (with speedup factor) |
Bottleneck | Internal phase that dominated HeliosDB execution time |
| Variable | Default | Description |
|---|---|---|
BENCH_WARMUP_SECS | 30 | Duration of warmup phase |
BENCH_MEASURE_SECS | 30 | Duration of measurement phase |
BENCH_ITERATIONS | 20 | Iterations per query category (embedded benchmarks) |
PG_CONNSTR | host=localhost port=25432 user=bench password=benchpass dbname=benchdb | PostgreSQL connection string |
We believe in full disclosure about what our benchmarks do and do not show:
Last updated: February 2026. Benchmark code and results are available in the benchmarks/ and tests/ directories of the HeliosDB repository.
All benchmark code is open source. Verify our claims on your own hardware.