Benchmarks

The benchmarks measure three criteria: speed, accuracy and cost.

Benchmark infra

Everything is measured on an 8-vCPU Amazon EC2 instance (Ubuntu, us-west-2) with the harness in the repo (bench/ann), calling the database code directly. The cloud-storage tests ran against three stores: the local disk, MinIO (S3-compatible store on the same machine), and Amazon S3 in the same AWS region.

The 10-million-vector tier ran on a memory-optimized instance of the same generation (r7i.2xlarge, 8 vCPU / 64 GB); the 100-million-vector tier ran on 16 vCPU / 128 GB (r7i.4xlarge, us-east-2), with its cloud-storage tests against an S3 bucket in that same region.

Accuracy here means: of the 10 truly closest matches, what share did the search actually return (the standard measure called recall@10).

Note: this page covers the vector-search paths. Hybrid search (BM25 + rank fusion) and filtered search are shipped features but not benchmarked here yet.

The short version

The headline numbers primarily revolve around costs. About $3.20 per million searches served straight from cloud storage with no index in RAM — that's at the 8-region setting, which measured 84% accuracy on the 1M test; the 98%-accuracy setting checks 32 regions and costs about $12.80. And about $0.01 per million writes through a write log kept directly in the bucket — no separate queue server (like Kafka) in the middle. When everything is hot, polign_db's in-RAM path answers in well under a millisecond — though the RAM-resident engines in the comparison below are faster still.

ScenarioMeasured result
Search from memory — 1M vectors, 128-dim (SIFT1M) 2,860 searches/sec at 96.5% accuracy; 950/sec at 99.4%
Search from memory — 1M vectors, 768-dim (cohere) ~505 searches/sec at 94.6% accuracy
Search from memory — 10M vectors, 128-dim (BigANN) 1,095 searches/sec at 95.6% accuracy; ~150/sec at 99.5%
Search from memory — 100M vectors, 128-dim (BigANN, 16-vCPU machine) 869 searches/sec at 95.5% accuracy; ~150/sec at 99.5%
Search straight from cloud storage — no index in RAM 18 ms typical — 27 ms even in the slowest 1% of searches (p99) — at 98% accuracy (same-machine store); ~144 ms typical, ~354 ms p99, against Amazon S3 in the same region
Search straight from cloud storage — 10M vectors 95.3% accuracy at 283 ms typical (32 regions); 78.9% at 118 ms (8 regions), against Amazon S3 in the same region
Search straight from cloud storage — 100M vectors 91.6% accuracy at 385 ms typical (32 regions); 85.1% at 215 ms (16 regions), against Amazon S3 in the same region
What a cloud-storage search costs ~$3.20 per million searches at 8 regions checked ($0.40 per million S3 downloads × 8; 84% accuracy on the measured 1M split — the 98% setting checks 32 regions, ~$12.80) — no RAM or idle servers on the bill
Compressed index — 32× smaller in RAM 97.4% accuracy with the re-check pass, ~330 searches/sec
Compressed index — 100M vectors, 16× smaller (16-vCPU machine) 98.8% accuracy with the re-check pass, ~300 searches/sec
Writes through the S3 write log (no queue server in the middle) 6,200 writes/sec per log at ~161 ms typical, ~286 ms p99 confirmation; ~$0.01 per million writes. That's the single-log worst case — the default deployment runs 16 logs, ~100,000/sec aggregate (arithmetic, not a separate measurement)

Comparison with other databases

The architectural comparison behind these benchmarks is detailed here - comparison page.

Search speed — in memory

Each curve below is a trade-off from fast-and-rough to slow-and-thorough.

Search speed — cloud-native storage

Polign cold search is executed with no index in memory at all. Each search downloads just the pieces of the index it needs from a storage bucket (S3, GCS, Azure Blob, MinIO) and searches them on the spot. That makes the cost of a search unusually easy to state, because cloud storage bills per download: a search that checks 8 regions of the index makes 8 downloads, and at S3's price of $0.40 per million downloads, a million such searches cost about $3.20.

How big each download is gets decided when the index is built: splitting the same data into fewer regions means bigger files but fewer downloads per search. Here is what three different splits of the same 1-million-vector dataset produced:

Cold search costs

The defaults are S3 list prices; downloads within the same AWS region carry no bandwidth charge, so bandwidth only matters for cross-region or internet clients.

Downloads per search
one file per region checked
Data downloaded per search
measured average file size
Accuracy at this setting
measured on the 1M-vector test
Cost per 1M searches
downloads only

Write speed and cost

In this setup, every write is appended to a log that lives in the storage bucket itself. When many writers are active at once, writes that queue up behind an upload already in flight all ride along in the next one. So a single upload can carry hundreds of writes.

That batching is the entire difference between 33 and 6,233 writes per second measured against the same S3 bucket. It also sets the cost: S3 charges $5.00 per million uploads, so the cost of a write is that price divided by how many writes share an upload.

The default deployment spreads writes across 16 logs, and because the logs never coordinate, throughput scales with the log count. The measured ~6,200/sec per log puts the 16-log default at roughly 100,000 writes/sec aggregate.

Concurrent write safety

Writers don't coordinate in advance. If two try to append at the same moment, the storage itself accepts one and rejects the other, and the loser simply retries at the next position. Nothing is ever lost or overwritten. A collision only costs one extra billed upload. The numbers below are two writer processes deliberately fighting over one log:

Compression. Smaller index, nearly the same answers

Instead of keeping every full vector, Polign can keep a compact fingerprint of each one — 8–64× smaller in the tests below (the headline numbers on this page use the 32× setting). Searching fingerprints alone gives up some accuracy, so an optional second pass re-checks the top candidates against the true vectors before answering. The charts show how much accuracy the fingerprints alone give up, and how much of it the re-check wins back.

Scale test with 10 million and 100 million vectors

This section reruns the same three paths — memory, cloud storage, compression — at 10× and 100× the data, using the 10M and 100M slices of the BigANN benchmark (SIFT1B). BigANN publishes official answer keys at exactly these sizes, so the accuracy numbers are verified against the same ground truth.

Both indexes scale the region count with the corpus: 4,096 regions at 10M, 16,384 at 100M.

The 10M tier ran on the same 8-vCPU class as everything above; the 100M tier needed a bigger machine — 16 vCPU / 128 GB (r7i.4xlarge). Build times: 7.3 minutes in memory at 10M, 115 minutes at 100M.

The cloud-storage indexes came to 6.6 GB (4,096 files) and 65.6 GB (16,384 files) respectively.

In short: at scale, search time is still bounded by the storage round trip. A one-region cold search costs ~80 ms median at 1M, ~87 ms at 10M, and ~96 ms at 100M. The median region file grew from ~0.6 MB at 1M to ~3.5 MB at 100M and the median barely moved, because S3's per-download first-touch price dominates the bytes.

Compression at scale: fingerprints are 8–64× smaller than the raw vectors, and the compressed tier checks a fixed 128 regions per search regardless of corpus size — so speed barely moves with scale: ~300 searches/sec for 32-byte codes at both 10M (8 vCPU) and 100M (16 vCPU), at 25 and 46 ms median. Deepening the re-check pool buys back the accuracy the fixed probe gives up: at 100M, 32-byte codes reach 98.8% with a 100-deep re-check and 16-byte codes 98.6% re-checking 500; at 10M the same settings reach 99.4%+. Two caveats: the bounded scan concedes the last point of accuracy (a wide probe hit 99.75% at 100M, but at 1/70th the speed), and 8-byte codes stay weak at scale — 91.1% at 100M even re-checking 500, their ranking too coarse for all the true neighbours to make the pool. With the full vectors in same-region S3 instead of RAM, re-check depth is fetch traffic: 50/100/200/500 finalists cost 26/52/104/255 MB per search for 89.3/96.7/99.3/99.7% accuracy at 0.46–2.5 s median (measured at 10M) — the chart's data table has the full breakdown.

Serving from a compressed replica

A replica node holds only the fingerprints in RAM (1.6 GB of fingerprints, ~2 GB structure in total, at 100M); the full vectors stay in cloud storage, and each search re-checks its finalists by downloading only the few kilobytes it needs from inside each file.

Run these yourself

Everything on this page can be regenerated from the repository:

# fetch datasets into bench/ann/data (SIFT1M + VectorDBBench cohere_medium_1m)
go build -tags cloud -o bench/ann/ann ./bench/ann
bench/ann/run_all.sh          # writes bench/ann/results/*.json
SCALE=10m bench/ann/run_scale.sh  # the 10M/100M tiers (SCALE=100m; BigANN subsets, see bench/ann/README.md)
bench/ann/gen_webdata.py      # regenerates assets/js/bench-data.js for this page

Every chart has a "view data as table" toggle, and the raw JSON reports (including median and worst-case timings for every point) are committed alongside the harness.