Each shard only sees a subset, so a global top-k requires merging
Because each shard holds only a subset of the collection's points, a shard's top-k is the top-k within that subset, not within the whole collection. If you simply concatenated the per-shard top-k lists, you would get a list of k times shard_count candidates, and the true global nearest neighbors could be ranked below candidates that happened to be in the same shard as each other. The correct global top-k requires two things: each shard must return more than k candidates (at least k plus any offset, and often more to account for the fact that the global ranking can pull from any shard), and the coordinator must merge the candidate sets by score and take the global top-k. This is the standard distributed top-k merge, and it is the only way to get the same result you would get from a single-shard search.
The mechanism is straightforward but easy to get wrong. The coordinator sends the query to every relevant shard with a per-shard limit that is at least the global limit plus the offset. If the query has offset=100 and limit=10, each shard must return 110 results, because the global 11th through 110th results could all come from a single shard. If the query involves a fusion stage (for example, Reciprocal Rank Fusion of a dense and sparse retriever), the merge is not a score sort but a rank-based fusion: the coordinator fuses the per-shard lists before taking the global top-k. This is why the fusion semantics matter: merging by score and merging by rank produce different results, and the coordinator has to apply the same fusion that a single-shard query would. For multi-stage queries expressed with prefetch, each stage's merge happens at the coordinator, and the candidate set passed to the next stage is the merged result, not the concatenation of per-shard lists.
Per-shard limit must be at least global limit + offset, or the global top-k can be wrong.
Merge is by score for a single-stage query, or by the fusion function (e.g. RRF) for a hybrid query.
Concatenation is wrong: it can put a shard's local top-1 above the true global top-1.
Multi-stage queries merge at each stage; the candidate set for the next stage is the merged result.
The coordinator's merge cost grows with shard count and with the per-shard limit, which is why shard count is a tuning parameter.
The trade-off is result correctness against coordinator cost. Requesting more than k from each shard is necessary for correctness but increases the data transferred to the coordinator and the cost of the merge. The coordinator's work is proportional to shard_count times per_shard_limit, so at high shard counts and large limits the merge itself becomes a bottleneck. The common mistake is thinking that concatenating per-shard top-k is a reasonable approximation. It is not - it can systematically favor shards that happen to contain many similar points, and the error is not bounded. The second mistake is forgetting the offset. A query with offset=1000 and limit=10 that requests only 10 per shard will return the wrong results, because the global top-1010 almost certainly includes more than 10 results from at least one shard. The third mistake is applying a score-based merge to a hybrid query that used rank-based fusion on the shards; the merge must use the same fusion function. Version note: the prefetch/fusion API and the exact merge semantics for multi-stage queries are recent additions and have changed across releases; the coordinator's behavior under fusion is version-specific.
Version-dependent: the prefetch and fusion API, the supported fusion modes (RRF, DBSF), and the exact merge semantics at each stage have evolved across releases. In older versions, multi-stage retrieval was orchestrated in the application layer, which meant the merge happened in the client and the per-shard limit was your responsibility. In newer versions, the coordinator handles the nesting, and the per-shard limit is derived from the stage's limit. If you are debugging a result discrepancy between a single-shard and multi-shard deployment, check the version's merge behavior first, because it is the most likely source of a subtle difference.
You have a 4-shard collection and query with limit=10 without offset. Explain why each shard returns 10 results and why the coordinator does not just concatenate them.
A teammate implements a client-side merge by concatenating per-shard results. Explain what is wrong with that.
You run a query with offset=500 and limit=10 on an 8-shard collection. Explain how many results each shard must return and what happens if Qdrant requested only 10.
You compare results from a 1-shard and an 8-shard deployment of the same data and they differ. Diagnose whether the merge is the cause and how you would confirm.
Design a hybrid retrieval pipeline with dense and sparse prefetch, RRF fusion, and a reranker, on a 16-shard collection. Explain where the merge happens at each stage and how you would validate correctness.
Your coordinator is CPU-bound during merges at high QPS. Explain the cost model and propose two ways to reduce the merge cost without changing the shard count.
Derive the minimum per-shard limit required for a correct global top-k as a function of shard count, global limit, and offset, and explain when the bound is tight versus loose.
You are designing a query coordinator for a sharded vector search system. Describe the merge algorithm, its complexity, and how you would handle a shard that returns late or fails entirely.