Filtered queries are often bottlenecked on payload lookups, not distance math
A filtered query does more than a vector search. Before and during the graph traversal, the engine has to evaluate the filter for each candidate - reading the payload value, checking the index, or looking up a posting list. If the filter is evaluated for every candidate the traversal visits, and the traversal visits hundreds or thousands of nodes, the payload lookups can outnumber the vector distance computations. When the payload index is in memory, those lookups are microseconds. When it is on disk and the pages are cold, each lookup can be a disk read, and the total cost of the filter evaluation can dominate the query. This is why moving payload storage on-disk can have a larger latency impact than moving vectors on-disk: vectors are read once per candidate at most, while payloads can be read many times per query, and the access pattern is more scattered.
The mechanism is that payload indexes are data structures with their own access patterns. A keyword index is a hash map from value to posting list; a range index is a sorted structure; a full-text index is an inverted index. All of these are accessed randomly during a filtered traversal, and their working set depends on the filter's selectivity and on the query distribution. A highly selective filter on a high-cardinality field touches a small part of the index, which may be a single page - cheap. A filter on a low-cardinality field, or a filter that matches a large fraction of the collection, touches a large part of the index, which may not fit in cache. The payload index for a large collection can itself be several gigabytes, so it competes for the same RAM as the vector data. If you move vectors to disk to save RAM but leave the payload index in memory, you have not solved the problem if the payload index is the bottleneck. Conversely, if you move the payload index to disk to save RAM but the vectors stay in memory, filtered queries can become much slower while unfiltered queries stay fast.
Lookup frequency: the filter is evaluated per candidate during traversal, so payload lookups can outnumber distance computations.
Index size: payload indexes for large collections can be gigabytes and compete with vectors for RAM.
Selectivity: selective filters touch a small part of the index; non-selective filters can touch most of it.
Unfiltered queries are unaffected: the payload location only matters when a filter is applied.
Access pattern: payload index access is random and scattered, which is worst-case for disk.
Practical rule: if filtered queries are the latency problem, check the payload index footprint and locality before moving vectors.
The trade-off is RAM for the payload index against filtered-query latency. Payload indexes are usually worth keeping in memory because they are smaller than the vector data and their access pattern is latency-critical. Vectors can often be moved on-disk with less impact on filtered queries, because the traversal distance computations can use quantized vectors that fit in RAM and only rescoring touches disk. The common mistake is to move everything on-disk to save RAM and then discover that filtered queries have become dramatically slower while unfiltered queries are barely affected. The second mistake is to create payload indexes that are far larger than necessary - indexing a field that is rarely filtered on, or choosing a heavier index type than needed, wastes RAM that could have gone to vectors. The third mistake is to assume the filter is free. It is not, and for selective filters it changes the traversal cost in ways that can dominate the query. Version note: the available payload index types and the way the planner uses them have changed across Qdrant releases; the on_disk option for payload storage and the optimizer thresholds that control it are also version-specific, so verify which settings your deployment exposes before planning a migration.
Version-dependent: the option to store payload indexes on disk and the optimizer thresholds that control it have changed across releases, and the planner's use of payload indexes has evolved. If you are tuning filtered-query latency, measure filtered and unfiltered queries separately on your version, and check the actual payload index footprint in the collection info rather than assuming it is small.
You move vectors on-disk and unfiltered queries are fine but filtered queries are much slower. Explain what is likely happening.
A teammate says the payload index is small and does not matter. Explain when that assumption is wrong.
You have a collection with five payload indexes and RAM is tight. Explain how you would decide which indexes to keep in memory and which to move or drop.
Filtered p99 is 5x unfiltered p99 on the same collection. Walk through the diagnosis and the fixes in priority order.
Design a payload index strategy for a collection with 15 filterable fields where queries use different subsets of fields. How would you balance index memory against filtered-query latency?
You must reduce RAM by 40 percent on a collection that serves mostly filtered queries. Propose a plan that does not regress filtered p99 significantly, and explain the trade-offs.
Derive the expected latency of a filtered query as a function of filter selectivity, payload index size, page-cache hit rate, and traversal length. Where does the model show that payload storage dominates vector storage?
You are designing a search engine where filtered queries are the dominant workload. Describe the storage layout, the index design, and the caching strategy, and identify the assumptions that could invalidate it.