ZBSearch

ZBSearch vs Orama

Head-to-head performance benchmarks comparing ZBSearch and Orama on the same workloads.

ZBSearch is a fork of Orama maintained by the original engineering team. The API is compatible, but the internals have been optimized - including an explicit postings list inverted index that lowers memory use and serialized bundle size while keeping search fast. This page summarizes benchmark results from the benchmarks/ suite in this repository.

Test environment

Results below were collected on July 10, 2026 using Orama 3.1.18 and ZBSearch 3.3.0, run via Benny for throughput and isolated Node.js processes (--expose-gc) for memory. Higher ops/s is better. Percentages show how much slower the loser is relative to the winner in each suite.

Summary

AreaVerdict
Full-text searchZBSearch is 11–58% faster on search; indexing is effectively equal
FacetsZBSearch is 28–56% faster across all facet scenarios
Vector searchZBSearch is 16–52% faster on flat indexes; IVF pushes gains to ~1,200–650% over Orama
Geosearch (BKD)ZBSearch is up to ~8,400% faster on radius queries at 500m
Sorted indexes (AVL)ZBSearch is faster on most AVL operations (insert, find, range search)
Memory footprintZBSearch uses ~6–8% less heap and RSS for the same indexed dataset
Persistence sizeZBSearch produces a ~4–7% smaller serialized bundle

Dataset: 1,512 video-game records with title, description, rating, and genres fields. Search benchmarks run against a database populated once before timing; insert benchmarks create a fresh database on each iteration.

BenchmarkOrama 3.1.18ZBSearch 3.3.0Difference
Plain search2,252 ops/s3,222 ops/sZBSearch 30.1% faster
Search with filters24,957 ops/s28,049 ops/sZBSearch 11.0% faster
Long text + complex filters5,252 ops/s12,415 ops/sZBSearch 57.7% faster

ZBSearch is faster across all search scenarios tested here, with the largest gap on long-text queries with complex filters. Indexing throughput is effectively identical between the two engines.

Facets

BenchmarkOrama 3.1.18ZBSearch 3.3.0Difference
Search with facets8,707 ops/s12,034 ops/sZBSearch 27.6% faster
Facets (all documents)2,522 ops/s4,561 ops/sZBSearch 44.7% faster
Facets + filters4,408 ops/s7,592 ops/sZBSearch 41.9% faster
Facets + long text + filters4,623 ops/s10,413 ops/sZBSearch 55.6% faster

Dataset: 2,000 documents, 128-dimensional vectors.

BenchmarkOrama 3.1.18ZBSearch 3.3.0 (flat)Difference
Vector search2,266 ops/s2,702 ops/sZBSearch 16.1% faster
Strict similarity4,532 ops/s6,889 ops/sZBSearch 34.2% faster
Vector + filters5,071 ops/s5,911 ops/sZBSearch 14.2% faster
Vector + facets1,273 ops/s1,895 ops/sZBSearch 32.8% faster

ZBSearch IVF vs Orama flat

ZBSearch adds an optional IVF index for approximate nearest-neighbor search. Orama does not ship an equivalent in the JS core.

BenchmarkOrama 3.1.18 (flat)ZBSearch 3.3.0 (flat)ZBSearch 3.3.0 (IVF)
Vector search2,229 ops/s2,715 ops/s30,530 ops/s
Strict similarity4,385 ops/s6,742 ops/s32,885 ops/s
Vector + filters5,106 ops/s5,915 ops/s22,927 ops/s

With IVF (nlist=179, nprobe=16), ZBSearch vector search is ~350–1,270% faster than Orama's flat index on this dataset.

Geosearch (BKD tree)

Dataset: 10,000 geopoints.

BenchmarkOrama 3.1.18ZBSearch 3.3.0Difference
Insert266 ops/s265 ops/s~equal
Search by radius (500m)3,649 ops/s308,894 ops/sZBSearch 98.8% faster
Search by radius (5km)3,047 ops/s4,735 ops/sZBSearch 35.6% faster
Search by radius sorted (5km)556 ops/s1,571 ops/sZBSearch 64.6% faster
Search by polygon3,227 ops/s3,958 ops/sZBSearch 18.5% faster
Contains (10k lookups)913 ops/s906 ops/s~equal

The largest geosearch gain is on tight-radius queries, where ZBSearch's BKD implementation avoids scanning the full point set.

Sorted indexes (AVL tree)

Dataset: 10,000 numeric keys.

BenchmarkOrama 3.1.18ZBSearch 3.3.0Difference
Insert411 ops/s529 ops/sZBSearch 22.3% faster
Insert batched (1k threshold)435 ops/s537 ops/sZBSearch 19.0% faster
Find (10k lookups)1,960 ops/s3,979 ops/sZBSearch 50.7% faster
Contains (10k lookups)2,330 ops/s3,121 ops/sZBSearch 25.3% faster
Range search (narrow)22,678 ops/s48,937 ops/sZBSearch 53.7% faster
Range search (wide)5,477 ops/s6,238 ops/sZBSearch 12.2% faster
Greater than6,147 ops/s6,683 ops/sZBSearch 8.0% faster
Less than6,776 ops/s6,902 ops/sZBSearch 1.8% faster
Remove (5k keys)400 ops/s489 ops/sZBSearch 18.2% faster

Inverted index (postings)

Starting in 3.3.0, ZBSearch stores full-text doc IDs in explicit posting lists outside the radix tree dictionary. The radix tree handles prefix navigation and typo tolerance; postings map each token to its document IDs.

This removes duplication that existed between inline radix Sets, tokenOccurrences, and scattered serialization of doc ID arrays. On save, posting lists are delta-encoded (sorted doc IDs stored as gaps), which shrinks the bundle without changing search semantics.

At runtime, document frequency for BM25 is derived directly from posting list length - no separate counter map is maintained.

Memory footprint

Measured in isolated Node.js processes with --expose-gc, after indexing all 1,512 records and running 100 warmup searches. Heap delta is the increase over a GC'd baseline after the index is built - the most apples-to-apples comparison.

MetricOrama 3.1.18ZBSearch 3.3.0Difference
Indexed heap delta17.12 MB15.69 MBZBSearch 8.4% lower
Indexed RSS delta51.13 MB47.77 MBZBSearch 6.6% lower
Search heap delta (100 queries)121 KB129 KB~equal

Search working-set memory is effectively the same; the savings come from the index structure itself.

Persistence size

Serializing the same indexed dataset produces a smaller bundle with ZBSearch 3.3.0:

EngineJSONGZIP
Orama 3.1.185,996,443 bytes1,425,900 bytes
ZBSearch 3.3.05,775,078 bytes1,329,786 bytes
Difference3.7% smaller6.7% smaller

The index portion of the bundle shrinks the most (~11.6% GZIP on index data alone) thanks to delta-encoded postings and dropping redundant tokenOccurrences from the serialized snapshot.

Run the benchmarks yourself

From the repository root, build ZBSearch first, then run any suite in benchmarks/:

cd packages/zbsearch && npm run build
cd ../../benchmarks && npm install

npm run benchmark              # core insert/search
npm run benchmark:facets       # facet workloads
npm run benchmark:vector       # vector search (flat)
npm run benchmark:vector-ivf   # vector flat vs IVF
npm run benchmark:bkd          # geosearch BKD tree
npm run benchmark:avl          # sorted AVL tree
npm run benchmark:bundle-size  # serialized DB size
npm run benchmark:memory       # in-memory heap/RSS footprint

Results are saved as JSON and HTML charts under benchmarks/benchmark/results/.

On this page