Benchmarks, honestly

Median of N runs, both engines warm, prepared statements on both sides, fsync to a real disk. Where SQLite wins, we show it — the chart is only useful if you can trust it.

AMD Ryzen 7 3700X · 32 GiB · ext4 on SATA SSD · rustc 1.95.0 · SQLite 3.50.2 · single-threaded

The scoreboard

Every CRUD operation, as a speed ratio. Right of the line, arkeion is faster; left of it, SQLite is — and yes, the full scan is still theirs.

0.5×evenSELECT by PKSELECT by PK — 567.9k vs 181.5k ops/s3.13×DELETE durableDELETE durable — 657 vs 263 ops/s2.5×INSERT durableINSERT durable — 656 vs 271 ops/s2.42×UPDATE durableUPDATE durable — 572 vs 278 ops/s2.06×SELECT by indexSELECT by index — 358.7k vs 181.6k ops/s1.98×Bulk-load APIBulk-load API — 2.59M vs 2.21M rows/s1.17×Batch insert (SQL)Batch insert (SQL) — 1.99M vs 1.94M rows/s1.02×Full scanFull scan — 8.07M vs 16.94M rows/s0.48×
Each dot wears the winner's color. Hover a dot for the raw numbers; the axis is logarithmic so 2× and ½× sit at equal distances from parity.

Durable writes — the core use case

Every committed transaction pays the fsync. arkeion's append-only commit needs one fdatasync; SQLite at synchronous=FULL pays two. On real disk that flips the table — and it's what an audited engine does constantly.

INSERT, durable 2.42× 656 vs 271 ops/s
UPDATE, durable 2.06× 572 vs 278 ops/s
DELETE, durable 2.50× 657 vs 263 ops/s

Full-text vs FTS5 — a split decision

The index ended up smaller than FTS5's; build and query speed are still FTS5's turf. The trade buys something FTS5 can't offer: versioned, provable, time-travelling search.

Index size, same corpus below FTS5
arkeion
arkeion: 26.2 MB
26.2 MB
SQLite
SQLite: 27.2 MB
27.2 MB

Prefix-compressed posting lists — and unlike FTS5, every posting is versioned, hash-chained and MATCH … AS OF searchable.

Index build (5.5M postings) FTS5 18× faster
arkeion
arkeion: 11 s
11 s
SQLite
SQLite: 0.6 s
0.6 s
Query, common term FTS5 2.3× faster
arkeion
arkeion: 2.5 ms
2.5 ms
SQLite
SQLite: 1.1 ms
1.1 ms

Vector search vs the field

SIFT 1M, 128 dimensions, L2, real top-100 ground truth, single query at recall ≈ 0.99. Under concurrent load it sustains ~700 qps on 8 cores; at recall ≈ 0.88 a single query does ~590 qps.

Throughput @ recall ≈ 0.99
Qdrant (HNSW)
Qdrant (HNSW): 508 qps
508 qps
arkeion (IVF-PQ)
arkeion (IVF-PQ): 356 qps
356 qps
pgvector HNSW
pgvector HNSW: 188 qps
188 qps
pgvector IVFFlat
pgvector IVFFlat: 63 qps
63 qps
Index size
pgvector HNSW
pgvector HNSW: 820 MB
820 MB
pgvector IVFFlat
pgvector IVFFlat: 551 MB
551 MB
arkeion (IVF-PQ)
arkeion (IVF-PQ): ~39 MB
~39 MB

14–21× smaller than the HNSW indexes — it fits in a fraction of the RAM. Qdrant does not report a comparable file size.

Index build
pgvector HNSW
pgvector HNSW: 324 s
324 s
arkeion (IVF-PQ)
arkeion (IVF-PQ): 64 s
64 s
Qdrant (HNSW)
Qdrant (HNSW): 49 s
49 s
pgvector IVFFlat
pgvector IVFFlat: 23 s
23 s

Parallel and streaming (186 s → 64 s): the dataset is never materialized, so it scales to tens of millions of rows on a modest box.

Read it fairly: pgvector and Qdrant answer over localhost TCP, so a 0.05–0.2 ms round trip inflates their latencies; and IVF scans O(N) candidates at fixed recall while HNSW is O(log N), so dedicated graph engines pull ahead at tens of millions of vectors. HNSW itself is excluded by design here — its random-access graph is incompatible with copy-on-write versioning and time travel. arkeion is the one file where vectors live next to SQL, full-text, branches and AS OF.

Smaller on disk

The same compressible dataset, written by both engines. Page packing plus pure-Rust LZSS — arkeion started this work at 4.0 MB.

Run them yourself

# CRUD vs SQLite (point at a real disk, not tmpfs)
ARKEION_BENCH_DIR=/path/on/real/disk cargo bench --features bench-sqlite

# on-disk footprint
cargo run --release --example dbsize --features bench-sqlite

A lesson we learned the hard way: on tmpfs the fsyncs are free and SQLite wins the durable writes. On a real disk it flips. Always bench on the disk you'll run on.

Convinced? It's one command away

Read the bench code