Hard zalando companies

When is exact kNN still the right choice in Elasticsearch, and what does approximate kNN cost?

The 30 second answer

Approximate kNN uses a graph index such as HNSW to find likely neighbours without scoring every document, so latency stays low on large sets. The cost is slower, memory-hungry indexing and recall below a hundred percent. Exact kNN scores every matching document, so it is precise but only fast when a filter first narrows the set. I tune candidates per shard against measured recall, and filter inside the kNN search.

Zalando's public Elasticsearch upgrade post gives this as the main product reason for moving from 7.17 to 8.x: the team already used vector search, but only the exact, brute-force kind, and wanted approximate kNN. That makes the trade-off a natural interview topic.

Exact kNN. A script_score query (or the exact dense_vector query) computes the vector similarity for every document that matches the surrounding query. Elastic's docs say it "guarantees accurate results but does not scale well for large datasets", and that latency improves if a filter narrows the set first. So exact kNN is right when the candidate set is already small: one merchant's assortment, a single category after strict filters, a re-ranking step over a few hundred lexical hits, or an evaluation job that needs the true neighbours as ground truth.

Approximate kNN. The top-level knn search uses a vector index (HNSW graphs, optionally with quantization) to visit only a fraction of the vectors. Elastic recommends it for most production workloads "where low latency and scale matter more than perfect recall". The costs:

  • Indexing. The dense_vector docs call indexing vectors for approximate search "an expensive process" that can take substantial time; every segment builds its own graph, and merges rebuild them.
  • Memory. The graphs want to live in the OS page cache for good latency, which competes with everything else on the node. Quantization reduces that footprint at some cost in precision. Which index type and quantization you get by default depends on the Elasticsearch version and the vector element type, so check the version's dense_vector docs rather than assuming.
  • Recall. Results are approximate. k is the number of neighbours returned, and num_candidates is "the number of nearest neighbor candidates to consider per shard". Raising num_candidates improves recall and costs latency.

Filtering. Put structured filters (category, size, in stock, market) in the kNN search's filter option so the search looks for the nearest neighbours among documents that pass the filter. Filtering the top results afterwards can leave fewer than k hits or none at all.

Hybrid retrieval. In product search, vectors usually complement lexical matching rather than replace it: exact brand and size tokens matter. Combine a lexical query and a knn leg, and fuse with a rank-based method or a weighted score, then evaluate offline before shipping.

How to tune honestly. Compute exact neighbours for a sample of real queries with brute force, then measure the recall of approximate search at several num_candidates values against latency. Pick the knee of the curve, not a number from a blog post.

Alternate interview scenarios

"Vector search returns nothing for some filtered queries. Why?"

If the filter is applied after an approximate search, the top candidates may all be filtered out. Move the filter into the kNN search, and check that the filter is not so selective that a brute-force search over the remaining documents would be cheaper; for very small filtered sets, exact kNN is the better tool.

"A new embedding model is ready. How do you roll it out?"

Vectors from two models are not comparable, so I index the new vectors into a new field or a new index, backfill the whole catalog, compare offline and in an A/B test, and switch reads with an alias or a query flag. Mixing old and new vectors in one field during a rollout would silently corrupt similarity.

Sources (4)
  1. Elasticsearch: kNN searchelastic.co
  2. Elasticsearch: Dense vector field typeelastic.co
  3. Elasticsearch API: Search (knn options)elastic.co
  4. Zalando Engineering: Migrating From Elasticsearch 7.17 to Elasticsearch 8.xengineering.zalando.com