Lead · Core path · 6 chapters
Metadata filtering
Pre- vs post-filtering, filtered-ANN recall cliffs, multi-tenancy isolation
A filter that is syntactically correct can still destroy recall or tenant isolation, so measure both before shipping multi-tenant retrieval.
Read these first
What you will know
Combine a filter with a vector search and measure recall
Use a labeled ground-truth set and report recall@k separately for filtered and unfiltered queries; aggregate averages can hide tenant-specific failures.
Demonstrate the recall cliff on a high-selectivity filter
When eligible documents are rarer than the ANN search budget, the index can exhaust candidates before finding enough matches and return short results without an error.
Choose pre- or post-filtering with a reason
Pre-filtering may protect correctness while increasing latency or reducing index efficiency; post-filtering may waste candidates and miss matches, depending on selectivity and the latency target.
Guarantee tenant isolation at the index level
Application predicates are vulnerable to missed code paths, cache contamination, and mis-scoped queries, so cross-tenant probes must fail at the storage or index boundary.
Detect a filter silently returning fewer results than it should
Compare requested k with eligible hits and alert against a trusted count or exhaustive baseline; otherwise truncation is easily mistaken for poor relevance.
Chapters
- 1
A filter can run before the search or after it, and the order changes the answer
Post-filtering asks the index for its top-k and then discards whatever does not match, so a predicate matching one document in a thousand usually leaves you with zero or one result out of ten blind candidates. Pre-filtering restricts the eligible set first and searches only inside it, paying in latency or lost index efficiency. Both are correct implementations; only one is correct for a given query.
- 2
The recall cliff appears when eligible documents are rarer than the search budget
A graph or cell traversal explores a bounded number of candidates. When matching documents are scarcer than that budget, the walk exhausts its allowance among ineligible neighbours and returns a short list with no error, no warning and normal latency. This chapter shows how to reproduce the cliff deliberately by sweeping selectivity from 10% down to 0.01% and watching results vanish.
- 3
At high selectivity the exact scan beats the index outright
Five thousand eligible vectors out of ten million is a brute-force problem: scan them all, get perfect recall, and finish faster than a filtered graph walk that keeps wandering into documents it must throw away. That is the third answer to pre-versus-post, and since selectivity varies query by query, the real design is a router that estimates how many documents the predicate matches and picks a plan from that estimate.
- 4
Filtered recall has to be measured apart from unfiltered recall
Against a labelled ground-truth set, report recall@k for filtered queries separately from unfiltered ones, and break the filtered figure down by the filter values your traffic actually uses. A single blended average stays comfortable while one tenant, one document type or one date range collapses, because those queries are a small fraction of the total and the mean absorbs them.
- 5
Two results when there should be twenty is truncation, not poor relevance
Users describe it as bad search, but the signature is a result count below k with normal latency. Detect it by comparing the number returned against an exact count of documents matching the predicate, and alert on the gap rather than waiting for a complaint. Then weigh the cheap fix — over-fetch and re-filter — against the real one, which is routing the query to a plan that respects its selectivity.
- 6
Tenant isolation enforced in the repository layer is not enforced
A tenant_id predicate added in one code path leaves every other path unguarded: a batch job, a new endpoint, an admin tool, and above all a result or embedding cache keyed without the tenant id, which serves one customer's documents to another with the predicate correctly applied. Push the boundary down to per-tenant namespaces, partitions or row-level security, then prove it with a cross-tenant probe that must fail at the store.
External resources
- A Complete Guide to Filtering in Vector Search — Qdrantqdrant.tech
Vendor-neutral treatment of pre-, post- and in-graph filtering with the failure modes
- Combining Vector Search and Filtering (Filterable HNSW)qdrant.tech
Hands-on payload indexes and filtered HNSW, the fix for the recall cliff
- The Achilles Heel of Vector Search: Filtersyudhiesh.github.io
Shows exactly how a selective filter collapses ANN recall, with measurements
- 4 context engineering strategies every AI engineer needs to knownewsletter.owainlewis.com
Walks through pre- and post-filtering, filtered-ANN recall cliffs, and multi-tenancy isolation.
- Context Engineeringblog.langchain.com
Explains metadata filtering tradeoffs, including pre/post-filtering, ANN recall cliffs, and multi-tenant isolation
- Metadata Filtering for Vector Search + Latest Filter TechJames Briggs
Pre vs post filtering explained visually, plus single-stage filtering approaches
- Qdrant Essentials | Combine Search & Filtering with Qdrant Filterable HNSWQdrant Vector Search
Practical tenant-isolation patterns via payload indexes on a real engine