Benchmark Comparison Tables
Benchmark Comparison Tables
This page keeps the benchmark numbers in comparison-friendly tables. It is a companion to Benchmark Notes, which contains the full conditions, reproduction notes, and interpretation.
These are local measurements, not universal performance claims.
PostgreSQL Reference
Environment summary: same machine as KoutenDB, AMD Ryzen 5 5600H, Linux 6.8, Nim 2.2.10, PostgreSQL 14.23, local TCP, single client, 100-byte payload where applicable. Measured on 2026-07-21.
Reproduction helper: N=10000 examples/postgres_bench.sh.
The helper creates a fresh temporary KoutenDB data directory and a fresh
temporary PostgreSQL cluster for each run, then removes them on exit.
Docker reproduction helper: N=10000 examples/postgres_docker_bench.sh.
| Group | Operation | us/op | Notes |
|---|---|---|---|
| KoutenDB | single-key read | 53.5 | Three koutend nodes, persistence enabled |
| KoutenDB | single-row write | 61.1 | Three koutend nodes, persistence enabled |
| KoutenDB | query projection | 61.1 | Server-side JSON projection |
| KoutenDB | strong-durability write | not measured | durStrong / --durability=strong was not part of this comparison |
| PostgreSQL 14.23 | primary-key SELECT |
86 | pgbench -M prepared, 11,570 tps |
| PostgreSQL 14.23 | single-row write, synchronous_commit=off |
104 | pgbench -M prepared, 9,621 tps |
| PostgreSQL 14.23 | single-row write, synchronous_commit=on |
1941 | pgbench -M prepared, 515 tps |
PostgreSQL Docker Reference
Environment summary: same host as KoutenDB, Docker overlay2, KoutenDB image
built from examples/compose/Dockerfile, PostgreSQL image postgres:14, same
Docker network, single client, 100-byte payload, n=10000. Data directories
are bind-mounted from a temporary helper directory during the helper run.
Measured on 2026-07-15.
Reproduction helper: N=10000 examples/postgres_docker_bench.sh.
The helper starts fresh KoutenDB and PostgreSQL containers on a fresh Docker
network and removes the containers, network, and temporary data directory on
exit.
| Group | Operation | us/op | Notes |
|---|---|---|---|
| KoutenDB Docker | single-key read | 61.3 | Three koutend containers |
| KoutenDB Docker | single-row write | 103.6 | Three koutend containers |
| KoutenDB Docker | query projection | 65.3 | Server-side JSON projection |
| PostgreSQL 14 Docker | primary-key SELECT |
103 | pgbench -M prepared, 9,669 tps |
| PostgreSQL 14 Docker | single-row write, synchronous_commit=off |
149 | pgbench -M prepared, 6,720 tps |
| PostgreSQL 14 Docker | single-row write, synchronous_commit=on |
1162 | pgbench -M prepared, 860 tps |
User Bundle PostgreSQL Reference
Environment summary: same machine as KoutenDB, AMD Ryzen 5 5600H, Linux 6.8, Nim 2.2.10, PostgreSQL 14.23, local temporary PostgreSQL cluster, single client, prepared statements. Measured on 2026-07-21.
Reproduction helper:
N=100000 READS=500 examples/user_bundle_postgres_bench.sh.
This benchmark is not a single primary-key lookup. It models a user-detail
bundle where each user has profile, addresses, career entries, preferences, and
orders. KoutenDB stores the records under coordinate-local rings such as
users/<id>/profile and reads the bundle with a narrowed stellar read.
PostgreSQL stores the same logical data in normalized indexed tables.
| Users | Logical records | Group | Query shape | read latency us |
|---|---|---|---|---|
| 1,000 | 20,000 | KoutenDB | users/<id>/* stellar depth read |
213.248 |
| 1,000 | 20,000 | PostgreSQL 14.23 | five indexed SELECT statements |
424 |
| 1,000 | 20,000 | PostgreSQL 14.23 | one JSON aggregate query | 246 |
| 10,000 | 200,000 | KoutenDB | users/<id>/* stellar depth read |
202.668 |
| 10,000 | 200,000 | PostgreSQL 14.23 | five indexed SELECT statements |
442 |
| 10,000 | 200,000 | PostgreSQL 14.23 | one JSON aggregate query | 257 |
| 100,000 | 2,000,000 | KoutenDB | users/<id>/* stellar depth read |
205.799 |
| 100,000 | 2,000,000 | PostgreSQL 14.23 | five indexed SELECT statements |
407 |
| 100,000 | 2,000,000 | PostgreSQL 14.23 | one JSON aggregate query | 240 |
The KoutenDB read path stayed roughly flat here because the query starts from
the user coordinate and only visits the requested subrings. The helper also
prints insertion and pack timings; the 100,000-user run inserted 2,000,000
logical records at 33.442073 us/record, which makes bulk load and many-ring
metadata creation clear follow-up optimization targets.
Heterogeneous Subring Bundle
This benchmark is closer to a real application detail endpoint: each related
collection has its own limit and sort order. KoutenDB reads a users/<id>/*
stellar neighborhood with per-subring options:
kouten get --ring=users/<id> \
--subring=profile,addresses,career,preferences,orders,notifications \
--subring-limit=profile:1,addresses:3,career:2,preferences:1,orders:10,notifications:5 \
--subring-rsort=orders:time,notifications:time
PostgreSQL stores the same logical data in normalized indexed tables. The
comparison includes both multiple indexed SELECT statements and a single
jsonb_build_object / jsonb_agg query with limited subqueries.
Reproduction helper:
N=10000 READS=1000 examples/subring_bundle_postgres_bench.sh
Measured on the same local machine as the other local PostgreSQL benchmarks:
AMD Ryzen 5 5600H, Linux 6.8, Nim 2.2.10, PostgreSQL 14.23, local temporary
PostgreSQL cluster, KoutenDB disk-backed mode, fresh temporary data directories,
single client, N=10000, READS=1000. Measured on 2026-07-21.
| Users | Logical records | Group | Query shape | Returned records | read latency us |
|---|---|---|---|---|---|
| 10,000 | 1,050,000 | KoutenDB | users/<id>/* stellar read with per-subring limits/sorts |
22 across 6 rings | 196.859 |
| 10,000 | 1,050,000 | PostgreSQL 14.23 | six indexed SELECT statements |
22 | 515 |
| 10,000 | 1,050,000 | PostgreSQL 14.23 | one JSON aggregate query over indexed limited subqueries | 1 JSON bundle | 236 |
This is not a universal PostgreSQL claim. It is a specific related-data bundle shape where KoutenDB can express the access pattern directly as bounded nearby subrings. PostgreSQL can express the same result with advanced SQL, but the query shape is no longer a plain join.
Redis Reference
Environment summary: same machine as KoutenDB, AMD Ryzen 5 5600H, Linux 6.8,
Nim 2.2.10, local Redis 6.0.16, one local koutend, buffered durability with
a fresh temporary data directory,
local TCP, single client, 100-byte payload, n=1000, Redis pipeline batch size
- Measured on 2026-07-21.
Local reproduction helper: N=1000 examples/redis_local_bench.sh.
The helper starts KoutenDB with a fresh temporary data directory and removes it
on exit. Redis local uses the configured Redis endpoint; the benchmark writes
under a unique koutendb:bench:<timestamp>: prefix and deletes those keys
before exit.
Docker reproduction helper: N=1000 examples/redis_docker_bench.sh.
The Docker helper starts fresh Redis and KoutenDB containers on a fresh Docker
network and removes them on exit.
| Group | Operation | us/op | Notes |
|---|---|---|---|
| KoutenDB | embedded get | 0.09 | In-process hot path; no TCP |
| KoutenDB | TCP GET | 52.88 | One request / one response |
| KoutenDB | TCP BGET | 1.81 | Batch read; comparable axis to Redis pipeline |
| Redis 6.0.16 | TCP GET | 44.93 | Non-pipelined local Redis |
| Redis 6.0.16 | pipeline GET | 3.55 | Batch size 256 |
Docker-Docker measurements under the same benchmark shape:
| Group | Operation | us/op | Notes |
|---|---|---|---|
| KoutenDB Docker | embedded get | 0.04 | In-process hot path inside the benchmark container |
| KoutenDB Docker | TCP GET | 55.78 | One request / one response across Docker network |
| KoutenDB Docker | TCP BGET | 1.71 | Batch read; comparable axis to Redis pipeline |
| Redis 7 Docker | TCP GET | 48.74 | Non-pipelined Redis on the same Docker network |
| Redis 7 Docker | pipeline GET | 2.06 | Batch size 256 |
Working-Set And Token Reduction
| Benchmark | Setup | Result |
|---|---|---|
| Working-set | 100 rings / 10k docs | scanned/query 10000 -> 100 |
| Memory-pressure | 100 rings / 100k docs / 512-byte payload | candidate memory/query 93.079 MiB -> 0.931 MiB |
| Synthetic RAG | fixed recall | recall 1.000, scanned/query 8000 -> 1000, tokens/query 3955 -> 657 |
| AI/RAG case study | generated JSONL, 400 docs / 6 rings | recall 1.000, scanned/query 400 -> 40, tokens/query 615.2 -> 231.6 |