A filter matches 0.1% of 100M vectors. Predict whether pre-filter brute force or post-filter ANN serves it faster.
A query carries a metadata filter matching just 100,000 of 100M vectors (0.1% selectivity). Option A: pre-filter, then brute force exact search over only the matching vectors (1024-dim float32, SIMD distance kernels available). Option B: run HNSW over the whole index and post-filter the candidates, oversampling until k=20 filtered results survive. Predict which option wins and roughly what each costs per query.
Pre-filter brute force wins at 0.1% selectivity: 100k SIMD dot products in milliseconds with perfect recall, versus post-filter ANN needing ~20,000 candidates that HNSW cannot deliver gracefully.
Picture searching for the tallest person at a stadium of 100,000 spectators. Two strategies. One: ask everyone wearing a red hat (you know there are only 100 of them) to line up and pick the tallest. Two: scan the whole stadium roughly, write down anyone tall-looking, then check which ones happen to have red hats, repeating until 20 of your tall candidates also wear red. If red hats are rare (one in a thousand), the first strategy finishes in seconds with the right answer. The second strategy spends ages scanning and most of the candidates fail the red-hat test, so you keep going. Vector databases face the same choice every time a filter is very selective.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
The brute-force versus ANN crossover for filtered queries is one of the most consequential and most overlooked decisions in production vector search. Teams pick one strategy at architecture time, ship it, and pay for it in tail latency on every query whose selectivity sits on the wrong side of the crossover. The right framing is to recognize that no single strategy is best; the strategy depends on per-query filter cardinality, and serious engines plan per query.
This section walks through the cost models for the three candidate strategies (pre-filter exact, post-filter ANN, filtered ANN), shows where each one wins, and discusses how real engines make the choice. The arithmetic is straightforward once the variables are named; the operational discipline is to never commit to one strategy globally.
Cost model: pre-filter exact scan
Pre-filter exact means apply the metadata filter first, then compute exact distances against the surviving vectors.
Filter application. A metadata index (B-tree on a scalar column, inverted index on a tag column, partition map on a partition key) identifies the matching vector IDs. At 0.1% selectivity, this returns 100,000 IDs out of 100M.
Distance computation. For each surviving vector, compute the query-to-vector distance. At 1024 dims float32, each distance is a 1024-element dot product. SIMD instructions (AVX2, AVX-512, NEON) process 8 to 16 floats per cycle; at modern clock speeds, a single CPU core can do roughly 10 billion floating-point operations per second on inner-product workloads.
Per-query cost.
Divided by 10 billion flops per second: roughly 20 milliseconds on a single core, single-digit milliseconds when SIMD and parallelism kick in.
Memory bandwidth. Reading the vectors is 100k x 4 KB = 400 MB. Modern memory bandwidth is tens of GB per second, so the read finishes in 10 to 30 milliseconds if the data is cold. If the filtered vectors are hot in cache, the read is free.
Recall. Exactly 1.0. Brute force is exact by construction.
Caveats. Storage layout matters. If the filtered vectors are packed contiguously (clustered, partitioned, or sorted by the filter column), the scan is sequential and bandwidth-friendly. If they are scattered, the scan is random I/O and pays a much higher per-byte cost. Cluster by frequently-filtered columns when possible.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- Qdrant has an explicit query planner that estimates filter cardinality and switches between pre-filter exact scan and filtered HNSW traversal automatically
- pgvector with HNSW now supports iterative scans that traverse the index while applying filters, with planner hints when statistics are wrong
What an interviewer would ask next. Try answering before peeking at the approach.
QWhat changes if the 100k filtered vectors are scattered across disk rather than packed together?
The scan turns into random reads, which are 100 to 1000x slower than sequential reads on disk. The arithmetic still says milliseconds, but the wall-clock time can be hundreds of milliseconds. The fix is storage layout: cluster or partition by the filter column.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Defaulting to ANN regardless of selectivity, then watching latency explode as oversampling factors balloon past what HNSW search lists can deliver.
60 second bullets to scan on the way to the call.
Why selectivity determines the right filter strategy, not absolute corpus size
How to compute the post-filter oversampling factor from k and selectivity
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.