The quick comparison
| How signals combine | Tuning | Best when | |
|---|---|---|---|
| RRF | Sum of 1/(k+rank) across lists (positions only) | None | You have no eval data; you want a robust default |
| Score fusion | Normalize scores, then weighted sum | Weights + normalization per workload | You can measure quality and tune weights |
| True hybrid | One query scores all signals, ranks once | Ranking expression | You want full control and no two-stage merge |
How does RRF work?
RRF combines lists using each document's rank, ignoring raw scores. Every document scores Σ 1/(k + rankᵢ) summed over the lists it appears in, with k conventionally 60 (from Cormack, Clarke & Büttcher, 2009). Because it only reads positions, it fuses lists whose scores live on incompatible scales (BM25's unbounded scores and cosine similarity's bounded ones) without any normalization.
Its strength is robustness with zero tuning, which makes it the standard first choice. Its weakness is that discarding scores discards information: RRF can't tell a document that barely made a list from one that dominated it, since both are judged only by rank.
How does score fusion work?
Score fusion keeps the raw scores, normalizes them onto a common scale, and combines them with weights, typically α · vector + (1−α) · lexical. Because it preserves each retriever's confidence, a well-tuned weight can beat RRF. Bruch et al. (2022) analyze fusion functions and find tuned convex combinations generally outperform rank-based fusion. You can lean on vector similarity for paraphrase-heavy queries and on lexical scores for exact-term queries.
The cost is tuning and fragility. Different score distributions need normalization (min-max, z-score, or similar), the weight α must be tuned per workload against evaluation data, and both can drift as your data changes. Score fusion rewards teams that can measure quality; it punishes teams that can't.
What is "true hybrid"?
True hybrid computes a single combined score in one retrieval pass instead of merging two independently-retrieved lists. Rather than running lexical and vector search separately and stitching the results, the engine evaluates all signals (keyword, dense, sparse, multi-vector, metadata) inside one query and produces one ranking.
Rank fusion (RRF / score fusion)
Two separate retrievals
Two truncated top-k lists
Merge afterwards
by rank or normalized score
Can only reorder what both lists caught
True hybrid
One query
All signals scored together
One ranking
No truncation before ranking
This removes a structural limitation of both fusion methods: post-hoc merges can only reorder documents that each retriever already returned in its top-k. A document strong on the combined signal but outside both individual top-k lists never gets the chance to rank. As TopK's case study puts it, rank fusion "can suppress relevant documents ranked moderately by both systems but overlooked by either individually." Scoring once, over the full candidate set, avoids that blind spot and gives you direct control over the ranking expression.
The gap is measurable. TopK benchmarked the three approaches on five BEIR datasets (July 2025, ModernBERT dense + SPLADE-v3 sparse): true hybrid improved nDCG@10 by 4.58% on average over RRF, up to 7.84% on TREC-COVID. The standard mitigation, overfetching 100 candidates per retriever before fusing, closed some of the gap but still lost by 3.10% on average, while doing more work per query.
Which should you use?
Start with RRF: it needs no tuning and is hard to beat out of the box, especially before you have labeled data. Move to score fusion once you can measure quality and want to exploit the confidence signal in raw scores. Reach for true hybrid when post-hoc merging is the limitation itself: when you need signals beyond two lists, want a document's combined score to decide its rank directly, or want to express custom ranking logic rather than tune a fusion weight.
TopK is built around the true-hybrid model: keyword, vector, and multi-vector retrieval with a custom ranking expression evaluated in a single query, so you don't assemble two retrievers and a fusion layer yourself. The fusion weights are literally one line:
from topk_sdk.query import select, field, fnfrom topk_sdk.data import f32_vector, f32_sparse_vectordocs = client.collection("docs").query(select(dense_score=fn.vector_distance("dense", f32_vector([...])),sparse_score=fn.vector_distance("sparse", f32_sparse_vector({...})),).sort(0.7 * field("dense_score") + 0.3 * field("sparse_score"), asc=False).limit(10))
The true hybrid search guide covers score normalization and the full expression syntax.