Skip to content
AI.info

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

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.

FigureComparison · 3 columns

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.

FigureProcess · 5 steps
  1. 1

    Canonical embeddings

    Generate versioned item vectors with validated norms and metadata.

  2. 2

    Index construction

    Choose graph, tree, partition, or quantization parameters.

  3. 3

    Filtering and sharding

    Apply eligibility without starving local or tail segments.

  4. 4

    Online query

    Search under latency, memory, and concurrency budgets.

  5. 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.

FigureProcess · 5 steps
  1. 1. Define quality ground truth

    Use exact search on representative queries and catalogs.

  2. 2. Sweep index parameters

    Measure recall, latency percentiles, memory, and build time.

  3. 3. Test filtering patterns

    Include sparse markets, rare attributes, and policy exclusions.

  4. 4. Exercise updates

    Measure insertion, deletion, rebuild, and rollback behavior.

  5. 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