Recommender systems
Approximate Nearest-Neighbor Search and Vector Indexes
Understand exact versus approximate search, recall-latency tradeoffs, vector normalization, filtering, sharding, and index lifecycle.
By the end you can
- Distinguish exact and approximate vector retrieval
- Explain how index, filtering, sharding, and compression affect candidate recall
- Design recall-latency-memory experiments with an exact reference
- Create index freshness, deletion, monitoring, and rollback controls
Key idea
A good embedding cannot survive a mistuned index
An accurate embedding model can still produce poor recommendations. It happens when the serving index approximates at the wrong operating point. The index is a separately measured object, and the field measures it that way. ANN-Benchmarks puts the exact baselines, bruteforce-blas and bf, on the same recall-against-queries-per-second axes as faiss-ivf, scann, hnswlib and pgvector. One set of vectors can be served at many different points. Each point is a different product.
Offline embedding quality certifies nothing about what users receive, because the vectors validated in training may not be the ones the serving index is answering with.
ANN search is a serving algorithm with its own error surface
Exact search computes the true nearest neighbors under the chosen score. On a large corpus it becomes costly. How costly is a measurable quantity, not a reason to skip it.
The FAISS GPU paper measured it in 2017. A k-selection kernel ran at up to 55% of theoretical peak. The nearest-neighbour implementation was 8.5x faster than the prior GPU state of the art. Its abstract states the consequence: “Our implementation enables the construction of a high accuracy k-NN graph on 95 million images from the Yfcc100M dataset in 35 minutes, and of a graph connecting 1 billion vectors in less than 12 hours on 4 Maxwell Titan X GPUs.”
At those numbers the reference is affordable. A team that cannot say whether a recall loss came from the model or from the index is usually choosing not to run it. It is not being prevented from running it.
Approximate indexes trade memory, latency, build time, update behavior, and recall. The effective candidate set also depends on filtering, sharding, replicas, vector normalization, and index freshness. All of those are system choices. Evaluate them separately from the embedding model.
Blaming the embedding model for a recall drop that filtering or a stale index caused sends the repair to the wrong layer of the system.
Case
ANN-Benchmarks reports a curve, not a score
An index is characterised by a curve, not a score. The tool the field uses says so on its own front page, describing its axes exactly: “The plot shown depicts Recall (the fraction of true nearest neighbors found, on average over all queries) against Queries per second.”
The scope is wide. As the ANN-Benchmarks leaderboard stood on 22 August 2026, it covered nine datasets under four distance measures. Angular: glove-100, glove-25, nytimes-256. Euclidean: fashion-mnist-784, gist-960, sift-128. Hamming: sift-256, word2bits-800. Jaccard: kosarak. It carried 38 algorithm implementations, from faiss-ivf, scann, hnswlib and pgvector down to the bruteforce-blas and bf exact baselines. Every one of them is reported as a curve.
That framing is the field’s, not one vendor’s. Malkov and Yashunin evaluate in the same frame. They claim “logarithmic complexity scaling” for a hierarchy of proximity graphs, and they report their gains at high recall rather than at a single operating point.
Choosing a point on that curve is a product decision. It belongs with the people who own latency.
Example
Filtering after the search, measured: 3,253 QPS against 37,671
The failure this section would otherwise describe in the abstract has been measured in public. The Big ANN Challenge at NeurIPS 2023 ran a dedicated filtered-search track. The corpus was a 10-million-image slice of YFCC100M encoded with CLIP. Each image carried tags drawn from a vocabulary of 200,386. The query set was 100,000 queries, each with one or two mandatory tags. Entries were scored on the highest throughput reached at recall@10 ≥ 0.9.
The organisers’ own baseline filtered after the search: “In vector-first mode, the search is performed with a Faiss IVF index and vector results that do not satisfy the word constraint are removed from the result list.”
That baseline reached 3,253 QPS on the private query set. The winning entry, ParlayANN, reached 37,671 QPS — more than 11x. Same vectors, same tags, same recall floor. Where the filter runs is not a detail of plumbing. On this track it was the whole result.
- Model quality: The track fixed the vectors — one 10-million-image slice of YFCC100M encoded with CLIP, identical for every entry — so nothing in the gap between 3,253 and 37,671 QPS is an embedding difference.
- Approximation loss: Throughput counted only at recall@10 ≥ 0.9. That is what makes the two figures comparable at all: an index is fast at a recall, never fast in general.
- Filtering loss: The baseline’s vector-first mode is post-filtering — search the vectors, then remove whatever fails the word constraint — and it is where the order-of-magnitude gap lives.
- Compression loss: Compressed codes reorder close candidates whatever the search does. On the GIST set, the 2011 product-quantization paper scans all 1,000,991 64-bit codes exhaustively in 17.2 ms and still returns recall of 0.652.
- Freshness loss: New items wait. Absorbing updates into a graph index normally means a periodic rebuild — the industry default FreshDiskANN was built to escape, at a claimed 5–10x reduction in the cost of maintaining freshness.
Comparison
Exact and approximate search answer different operational needs
Exact search is not really a competitor in this row. It is the reference the other two are measured against. ANN-Benchmarks treats it that way, carrying bruteforce-blas and bf on the same recall-against-queries-per-second axes as the approximate implementations.
Graph-based ANN buys recall at a given latency by spending memory. The result behind that sentence is HNSW, from Malkov and Yashunin in 2016. In their own words: “Starting search from the upper layer together with utilizing the scale separation boosts the performance compared to NSW and allows a logarithmic complexity scaling.” Their gains are claimed at high recall. That is precisely the qualifier a single quoted throughput figure drops.
Partition and quantization methods buy scale by accepting approximation. The canonical account is the 2011 product-quantization paper. Its IVFADC index is a coarse partition over compressed codes, with the number of visited cells left exposed as a knob.
Read the three together and the row stops being a ranking. It is one reference and two families with different knobs.
Exact search
Returns true neighbors for the implemented score.
- Useful as an evaluation reference
- Expensive on large corpora
- Simpler filtering semantics
- Supports sampled ground truth
Graph-based ANN
Traverses a proximity graph such as HNSW-like structures.
- High recall-latency performance
- Memory intensive
- Supports incremental insertion with caveats
- Sensitive to construction and search parameters
Partition and quantization methods
Reduce search and memory through coarse cells or compressed vectors.
- Scales to very large corpora
- Adds approximation and training choices
- Can affect close-score ordering
- Useful under strict memory budgets
Visual
The vector-search lifecycle
An index is a build artifact with a version, not a lookup table. Canonical embeddings are generated, the index is constructed, filtering and sharding decide eligibility, queries are served inside a latency budget. The last stage, refresh and rollback, is what decides whether a bad rebuild can be undone.
That last stage is structural rather than a matter of diligence. Absorbing updates into a graph index normally means building the index again from scratch. FreshDiskANN, a 2021 system from Microsoft Research, was built to escape that default, and its abstract names it: “To overcome this drawback, the current industry practice for manifesting updates into such indices is to periodically re-build these indices, which can be prohibitively expensive.”
Its alternative sustained thousands of concurrent inserts, deletes and searches per second on a billion-point index. That was on a single SSD workstation, while holding above 95% 5-recall@5. The authors put it at a 5–10x reduction in the cost of maintaining freshness. Either way the stage exists and carries a cost. What it must not be is unowned.
- 1
Canonical embeddings
Generate versioned item vectors with validated norms and metadata.
- 2
Index construction
Choose graph, tree, partition, or quantization parameters.
- 3
Filtering and sharding
Apply eligibility without starving local or tail segments.
- 4
Online query
Search under latency, memory, and concurrency budgets.
- 5
Refresh and rollback
Insert, delete, rebuild, compare, and revert index versions.
Example
Index failure modes
Model-index mismatch and no exact reference compound each other. Serving drifts onto stale vectors, or onto a different normalization. Without an exact search to compare against, nobody can say whether the lost recall came from the model or from the index.
The filtering failure has a literature and a vocabulary of its own. A 2025 survey in PVLDB names three execution methods: pre-filtering, post-filtering and inline filtering. It sets the target as “Stable recall: achieve consistent recall across queries, regardless of filter conditions or the execution method.” Every bullet below is a way of losing that consistency without losing a request.
- Model-index mismatch: Serving uses stale vectors or a different normalization from training, and the symptom is indistinguishable from a mistuned index until an exact reference separates the two.
- Post-filter starvation: Simple post-filtering must ask the ANN search for a multiple of K results just to keep K after the filter — an extra tuning parameter inline filtering does not need. The same survey records that a search tuned for unfiltered queries fails to reach high recall once filters are added.
- Shard imbalance: Regional or category shards have uneven recall and latency, which is the same defect under another name: recall that moves with the query rather than staying consistent across queries.
- Deletion lag: Unavailable or disallowed items remain retrievable for as long as the rebuild cycle takes, because periodically re-building the index is how updates reach a graph index by default.
- No exact reference: The team cannot tell whether recall loss comes from the model or the index — a choice rather than a constraint, when a high accuracy k-NN graph over 95 million images takes 35 minutes.
Steps
Choose and verify an ANN operating point
Ground truth for an approximate index is exact search on a sample. It has to exist before a parameter sweep can mean anything.
Here is what a sweep looks like when it is done and published. The 2011 product-quantization paper holds index, dataset and code size fixed — the GIST set, 500 queries, 64-bit codes (m=8, k*=256), IVFADC with k′=1024 — and moves one knob, the number of visited cells. At w=1 the search takes 1.5 ms and finds recall@100 of 0.308. At w=8 it takes 8.8 ms for 0.682. At w=64 it takes 65.9 ms for 0.744.
That is a 44x latency increase buying 0.436 recall. Most of the recall arrives in the first few steps. Exhaustive ADC over all 1,000,991 code comparisons sits off to the side at 17.2 ms for recall 0.652. The authors are explicit that this is the only fair way to compare such systems: “The IVFADC and FLANN methods are both evaluated at different operating points with respect to precision and search time.”
Filtering patterns, update behavior and index health carry the rest of the operating point. Exercise filters on sparse markets, rare attributes and policy exclusions. Measure insertion, deletion, rebuild and rollback. Monitor version, freshness, sampled recall, empty results and shard skew rather than the error rate.
1. Define quality ground truth
Use exact search on representative queries and catalogs.
2. Sweep index parameters
Measure recall, latency percentiles, memory, and build time.
3. Test filtering patterns
Include sparse markets, rare attributes, and policy exclusions.
4. Exercise updates
Measure insertion, deletion, rebuild, and rollback behavior.
5. Monitor index health
Track version, freshness, recall samples, empty results, and shard skew.
Key idea
The index gate
Ship an ANN configuration only when its recall, freshness, filtering behavior, resource use, and rollback path are known for the intended traffic.
A recall number read at the wrong moment is not a small error. The streaming track of the NeurIPS'23 Big ANN Challenge ran a runbook of 1,280 batches, insert:delete:search ≈ 4:4:1, under an 8 GB memory cap and a 1-hour bound. The organisers later disclosed: “Unfortunately, more than six months after the competition, we discovered that recall had been calculated incorrectly due to a caching error. The previous results reflected recall at the first snapshot in the runbook rather than averaged over the whole runbook.”
The fix was merged on 8 March 2024 and the rerun followed on 3 May 2024. It reversed the leaderboard. The declared winner, Puck, fell from a reported 0.985 to 0.0921, last of five. PyANNS rose from 0.9597 to 0.8865, and first.
If a refereed competition with a published harness can misread its own index for more than six months, an unmonitored production index can do it indefinitely.
Require the rollback path before the launch, not after the first quiet recall drop, since an index that degrades without erroring gives no other moment to act.
Key takeaways
- Approximate search is part of the recommendation policy, not an implementation detail. On one CLIP-encoded 10-million-image slice, filtering after the search ran at 3,253 QPS and the winning entry at 37,671.
- Exact search computes the true nearest neighbors under the chosen score, and on a large corpus it becomes costly — costly enough to sample rather than serve, not costly enough to skip. A high accuracy k-NN graph over 95 million images took 35 minutes on 4 Maxwell Titan X GPUs.
- An accurate embedding model can still produce poor recommendations when the serving index approximates at the wrong operating point. That is why ANN-Benchmarks reports every one of its 38 implementations as recall against queries per second instead of as a score.
- Canonical embeddings are a build input, not a lookup table. The index is a versioned artifact over them, and while periodically re-building remains the industry practice for absorbing updates, the serving copy is always a snapshot of an earlier moment.
- Model-index mismatch remains a practical risk: serving uses stale vectors or a different normalization from training, and only an exact reference run on a sample tells that apart from a mistuned index.
- A serving index degrades quietly, so its version, freshness, sampled recall, empty-result rate and shard skew all need continuous tracking. The streaming track's cached recall read 0.985 where the corrected run read 0.0921.