The vector database

The Elasticsearch essays · March 2026

Everything else in this series matches and counts symbols. But "the checkout is broken" and "customers can't complete purchases" share no symbols at all, and no inverted index will ever connect them. This essay is about the leap past symbols: vectors, the graphs that navigate them, the compression that makes them affordable, and the fusion that lets the lexical and semantic judges vote together.

1 · Meaning: the vector store

Modern language models offer an exit: they convert text into a list of numbers, an embedding, such that similar meanings land near each other. Search-by-meaning becomes geometry: embed the query, find the nearest neighbors.

Where do the embeddings come from? Elasticsearch runs the models itself. Its own ELSER model produces sparse vectors, a bag of weighted concept-words, interpretable and served by the familiar inverted index; and since acquiring Jina AI, it also serves Jina's dense multilingual and multimodal embedding models and its cross-encoder rerankers through its inference service. Map a field as semantic_text and the machine embeds every document, and every query, automatically.

Finding nearest neighbors by measuring every distance would be a full scan, the very thing this machine exists to avoid. So vectors get an index too: HNSW, a web of neighbor links a query can greedily hop across. (How that web is built, why it has layers, and its one crucial tuning dial fill an essay of their own: HNSW: the graph that finds meaning.) Drag the query, then turn on the graph:

3
Drag the dark query point. With the graph on, the orange path is the greedy walk from a fixed entry point: a handful of hops instead of 52 distance checks.
Now add a filter and drag the query far from the matching cluster: the answers stay within the filter, however far you roam, and the distance count climbs: the walk has to cross non-matching ground to get there. Filtering after a vector search can starve you of results; Elasticsearch filters during the graph walk instead, traversing non-matching points but never returning them.

There is one problem left, and it's the one that decides whether vector search is affordable: memory. A single 1024-dimension embedding in full precision costs 4 KB, and a graph walk is only fast when the vectors it compares sit in memory. A hundred million documents would need 400 GB for the vectors alone. Elasticsearch's answer, and a place where it has pushed the state of the art, is BBQ, Better Binary Quantization: compress each dimension to roughly one bit, carrying corrective statistics so the compressed comparisons stay honest:

RAM for 100M vectors
per vector
compression
recall@10 · compressed only
recall@10 · 3× rescored
float32int8BBQ · 1 bit
Drag precision down and watch the same 24 dimensions coarsen: full floats, then small integers, then single bits. Memory for 100 million 1024-dimension vectors collapses from 410 GB to about 14 GB. The two recall numbers are measured live, on 2,000 synthetic vectors and 20 queries: compressed scores alone lose more and more of the true top ten as precision falls, but fetching three times as many candidates and re-checking them against the exact values wins most of it back. Real embeddings are friendlier than this random data; the shape of the trade is the same. BBQ is Elasticsearch's default for vectors of 384 dimensions or more.

"Search generously, then re-check" deserves its own dials, because oversampling is the mechanism that buys BBQ's memory savings back its accuracy. Compressed scores are noisy, so the true best answers are probably near the top of the compressed ranking, but not exactly at it. Fetch extra candidates, rescore them exactly, keep the winners:

–
true top-10 recovered
–
exact rescores paid
1×
Each chip is a candidate ranked by its noisy compressed score; green chips are documents that truly belong in the top ten. At 1×, whatever noise pushed out of the window is lost. Slide to 3×: nearly every green chip is back inside the net, and the exact rescoring of thirty vectors costs almost nothing next to the full-precision search you avoided. Crank the noise to see why deeper compression simply needs a wider net.

A database under the vectors

The graph is not the only layout either. Since 9.4, where the license allows it, Elasticsearch defaults new vector fields to bbq_disk: the same one-bit compression, but vectors grouped into clusters (a variant of k-means) instead of linked in a graph. Without that license the default remains an HNSW graph with BBQ above 384 dimensions.

Compression and clever graphs are what make vector search possible; what makes it usable is everything this machine already was. A dedicated vector index holds vectors; Elasticsearch holds vectors next to the document they came from, so the filtered search you just tried above, "similar to this, but only in checkout, only this week", is one query, with the filters answered by the keyword and BKD structures of the earlier chapters, honored during the graph walk. Vectors here are replicated by the same shards, aged by the same lifecycle policies, secured by the same permissions, aggregated by the same engine. A vector store bolted onto your stack is another database to operate; this one is a column in a database you already have.

Where the vectors come from, the models, the chunking of long documents, sparse versus dense embeddings, late interaction, rerankers, is a craft of its own: Semantic search in practice.

2 · Hybrid search: two judges are better than one

So the machine now has two ways to rank text: the lexical judge (BM25), unbeatable on exact words, product codes, error strings; and the semantic judge (vectors), which sees paraphrase and intent but can be vague about specifics. Which should you use? The honest answer is both, and the way Elasticsearch combines them is almost embarrassingly simple: reciprocal rank fusion. Ignore the incomparable scores entirely; look only at each document's rank in each list, and award it 1/(k+rank) points per list:

Lexical · BM25
Semantic · vectors
Fused · RRF
60
The orange document tops neither list, but it's the only one both judges respect, and fusion finds it. Small k trusts the top ranks aggressively; large k flattens the vote.

For the final polish, the top of the fused list can be handed to a reranker, a heavier model (the Jina rerankers, in Elasticsearch's case) that reads query and document together and re-orders the finalists with far more care than any first-pass ranking could afford. Cheap judges to nominate candidates, an expensive judge for the podium, the machine's usual economics, applied to relevance itself.

The filters honored during the graph walk come from the search essay's structures; how all the stores answer one query together is the subject of The machine, whole.