BENCHMARKS · WINS AND LOSSES, WITH RECEIPTS

EVERY NUMBER HERE
TRACES TO A RUN.

Four things a search engine for AI agents has to prove, each measured, each linked to the harness or the case study that produced it: engine performance, code retrieval, token savings, and the design that ties them together — the zero-token architecture. The red cells are published too, root-caused with file:line, because a benchmark page that hides its losses is marketing.

6.5×
cheaper agent runs
$21.90 → $3.38 across 21 unfamiliar-API tasks, same Claude Code — reference-coding case study
21 / 21
tasks solved with retrieval
against 1 / 21 from model memory alone; hidden-test verdicts, real token accounting
55 W · 26 T · 4 L
vs Elasticsearch, 88 cells
audited board, cache-off, iso-load; every verdict shown — the full scorecard
11.7 ms
identifier lookup — code index
vs 15.3 ms for Sourcegraph's Zoekt and 260 ms for cold ripgrep, same 15-repo corpus, same box
01·PERFORMANCE · ENGINE + RESOURCES

FAST WHERE IT'S USED,
QUIET WHERE IT ISN'T.

Two performance stories matter for an engine that lives next to your agents: how fast a query comes back, and what the process costs when nobody is asking. Both are measured; neither is extrapolated.

MeasurementXERJComparisonVerdictSource
88-cell query board vs Elasticsearch 8.x — reads, aggs, pipelines, mixed, kNN, storage 55 wins26 ties · 4 losses · 3 n/a WINscorecard — one win is honestly a draw; the page says which
Server round-trip, size:0 over 300k docs, keep-alive client 0.126 msES 0.283 ms 2.2×scorecard · read transport
Bulk ingest, identical corpus and box 1.72× higherES baseline WINscorecard
On-disk size, same docs 176.2 MBES 283.0 MB 1.61× smallerscorecard · storage caveats apply
kNN k=10, HNSW-served with exact rescoring 1.76 msES 2.08 ms TIE (1.18×, inside noise)scorecard — recall is measured, never assumed
Identifier lookup, one index, 15-repo code corpus (p50 of 21) 11.7 msZoekt (Sourcegraph) 15.3 ms · ripgrep cold 260 ms WIN per-index2026-08-29 session, same box, released rc.70 binary
Mixed read-under-write p99, 40k docs/s iso-load writer 10.3–13.6 msES 3.5–6.8 ms 4 LOSSESscorecard · root-caused to a lock, fix targeted
HEAD-TO-HEAD · THE TOOLS A DEV MACHINE ACTUALLY RUNS · 15 REPOS · 154 MB · SAME BOX, SAME HOUR
DimensionXERJ rc.70/71Zoekt (Sourcegraph)ripgrepWhat it means for you
Identifier search, p50 11.7 ms (one index)15.3 ms260 ms cold An agent that retrieves 50 times in a session waits ~0.6 s total, not 13 s — retrieval stops being the slow step in the loop.
— across all 41 datasets today 701 ms15.3 ms260 ms Our multi-index fan-out is serial today — measured, filed, fix scoped (#875: expected ~20–30 ms).
Exact phrase, p50 829 ms (fan-out)37.9 ms200 ms Same #875 fan-out defect; the per-index engine is competitive once the query reaches it.
Regex over source not offered870 ms180 ms Nobody owns this today — Zoekt's regex loses to cold grep at this corpus size. A trigram side-car is on our roadmap precisely because the category is open.
Index 15 repos 676 s + merge tail302 s0 s (no index) XERJ's indexer does strictly more work — AST symbols in 13 languages and graph edges, not just trigrams — but the merge tail is a defect, not a feature (#876).
Idle daemon, this corpus 8% CPU · 8.3 GB0.03% · 119 MBnone Today's honest loss. Root-caused to three mechanisms with a published budget — idle under 0.5% of one core at any index count (#874).
Symbol / definition ranking built in, 13 languagesneeds universal-ctags installednone One binary gives your agent definition-first ranking with no sidecar toolchain to install or keep in sync.
Beyond code search ES wire · aggregations · kNN vectors · agent memorycode search onlygrep only The same daemon that answers your agent's code lookups holds its logs, vectors and memory — one thing to run instead of three.

Method: released XERJ binaries, Zoekt built from source at HEAD, ripgrep 14.1.1; identical 15-repo corpus (memcached, valkey, tantivy, regex, zstd, CRoaring, …), p50 of 21 requests per cell, CPU and RSS from /proc. Zoekt indexed serially per its defaults; XERJ's indexer also extracts AST symbols and graph edges, which Zoekt does not attempt — stated so the wall-clock rows are read fairly. Result quality (ranking, symbol precision) is not scored here.

The losses, on purpose. Four cells on the Elasticsearch board — read p99 under a 40,000 docs/s writer — are red, root-caused on the scorecard to reader starvation on a live memtable lock. Against Zoekt, today's red cells are multi-repo fan-out, indexing wall-clock, and idle footprint — every one measured above, filed the same day with the mechanism at file:line (#871#876). That is the deal this page offers: competitors are named, the red cells get the same precision as the green ones, and each red cell links to its fix.
02·RETRIEVAL · CODE THE MODEL DOESN'T KNOW

CORRECT WHERE
MEMORY FAILS.

The retrieval claim is not "search is nice" — it is that retrieval makes the same model correct on APIs it has never memorised. Measured across 13 purpose-built libraries in 5 languages (unfamiliar by construction, so the model cannot bluff), with hidden-test verdicts and real token accounting from claude -p.

TASKS SOLVED · 21 RUNS · UNFAMILIAR CONTRACT DOMAINS
bare — model memory only XERJ — reference retrieved
1 / 21
21 / 21
bareXERJ
Unfamiliar APIs — compiles + passes a hidden test
0 / 9
9 / 9
bareXERJ
Hardest single library (sift, streaming sketch)

Method, per-library table, and every per-run record: the reference-coding case study · docs/case-studies/reference-coding

03·TOKEN SAVINGS · REAL ACCOUNTING, NO API KEY REQUIRED

THE TOKENS YOU
DON'T SPEND.

Output tokens are the expensive kind — priced roughly 5× above input on Claude models — and retry loops on unknown APIs burn exactly those. Three arms of the same agent on the same tasks: memory only, grep-driven, retrieval-injected. Every figure from claude -p --output-format json.

8 TASKS × PYTHON / JS / C / JAVA · 16 RUNS PER ARM
bare — memory only native — greps the source XERJ — reference retrieved
260,916
26,477
9,982
barenative XERJ2.7× fewer than native
Output tokens to solve — lower is better
$11.18
$3.27
$1.58
barenative XERJ7.1× cheaper than bare
Cost per matrix — real per-run pricing

The per-language medians run 6.7× (JavaScript) to 278× (Java) fewer output tokens than answering from memory. An independent 12-question dev-QA measurement on the engine's own reference corpora lands at 1.65× fewer output tokens and 1.47× cheaper — smaller, because it includes questions where the model already knew the answer; both numbers are published.

WHERE TOKENS GO WITHOUT RETRIEVAL

  • Retry loops. Invent a method name, fail to compile, loop — output tokens on every lap. Measured worst case: 27,108 tokens and a failing test.
  • Context stuffing. Grep recovery pulled up to 1.06M input tokens of source into context for one corpus.
  • Compiler archaeology. "Did you mean" recovers a name at 20–150× the tokens — and never a runtime rule.

WHERE THEY GO WITH IT

  • One query. A multi_match over defs/body/title, ~10 ms server-side.
  • One passage. The definition, its contract, its file:line — hundreds of tokens, not hundreds of thousands.
  • Measured floor. The same Java task that burned 27,108 tokens from memory: 98 tokens with the reference in hand. 278× fewer.
04·ZTA · THE DESIGN BEHIND THE NUMBERS

ZERO-TOKEN
ARCHITECTURE.

The cheapest token is the one your model never generates. ZTA is the design rule that produced every number above: spend compute once, at index time, so agents stop spending inference tokens — the metered, per-request, 5×-priced resource — re-deriving what the index already knows. It is an architecture target with measured proxies, not a certification; here are its four principles and the number that keeps each one honest.

ZTA-1

UNDERSTAND AT INDEX TIME

proxy: ~1,500 files/s extract · ~100× unchanged re-index

Parse the AST once — 13 languages, every symbol with kind and line, a ranked defs field — instead of letting every future question re-derive structure with tokens. Index-time compute is bought once; token-time compute is bought on every question, forever.

ZTA-2

ANSWER WITH THE PASSAGE, NOT THE CORPUS

proxy: 98-token solve vs 27,108 · 1.06M-token grep avoided

The unit of answer is the definition with its contract and file:line — never "here are eleven files, good luck." Small answers keep the agent's context small, which compounds: every later turn re-pays for everything already in the window.

ZTA-3

THE AGENT SETS ITSELF UP

proxy: one pasted line → verified end-to-end run

Setup instructions live at llms.txt in machine order: install, start, index, query, retrieval discipline. One pasted sentence turns it on — tested verbatim, transcript published. Zero tokens spent negotiating with documentation written for humans.

ZTA-4

IDLE COSTS NOTHING

proxy: budget < 0.5% of a core at any index count, published (#874)

An always-on corpus next to your agents must not tax the machine they work on. Zoekt sets the bar at 0.03% — the head-to-head above shows we are not there yet, and instead of hiding that, the remaining idle mechanisms are located, filed, and budgeted in public (#874). The rule the codebase now enforces: no per-index periodic work, ever.

Why this is the sales pitch and not a slogan: infrastructure used to compete on latency; agent infrastructure competes on your inference bill. A retrieval that answers in 10 ms and a few hundred tokens replaces a 15,000-token retry loop every time it fires — the $21.90 → $3.38 delta above is that substitution, measured 21 times over. ZTA is the commitment that every future XERJ feature is judged by the same question: how many tokens does it stop your model from spending?

RUN THE NUMBERS ON YOUR CODE.

THE FULL ES SCORECARD → THE TOKEN CASE STUDY GET XERJ