RRF is the safe default for hybrid search fusion, a tuned linear combination of normalized scores usually beats it once you have judged queries, and a re-ranker often matters more than either. Benchmarks, engine settings and a decision checklist.
Hybrid search fusion is the step that merges a lexical (BM25) ranked list and a vector ranked list into one ordering. Engines offer two families of fusion - rank-based, like Reciprocal Rank Fusion (RRF), and score-based, like min-max or z-score normalization followed by a weighted sum - and most also let you add a re-ranking stage on top. Picking between them is the relevance decision that most hybrid setups get wrong. If you need the basics first, start with our hybrid search explainer.
The short answer, from the published research and from tuning Elasticsearch and OpenSearch relevance for clients: use RRF when you have no relevance judgments, and switch to a tuned linear combination once you have a few dozen judged queries. If top-of-list precision matters, a re-ranker will move your metrics more than either. And none of it helps if one retriever is weak.
How RRF, score normalization and re-ranking fuse results
Rank-based fusion throws scores away and keeps positions. RRF scores each document as the sum of 1 / (k + rank) across retrievers, with k = 60 from Cormack, Clarke and Büttcher (SIGIR 2009). Weighted RRF multiplies each retriever's term by a weight. We cover the math in our RRF deep dive. The appeal is that RRF never has to reconcile a BM25 score of 24 with a cosine similarity of 0.82. The cost: as Qdrant's fusion course puts it, "RRF knows only that a document came first, second, or third." A runaway top match and a photo finish get the same credit.
Score-based fusion keeps the scores, rescales each list onto a comparable range, then takes a weighted sum: α · dense + (1 − α) · lexical. This is also called linear combination or convex combination. The normalizer is the main design choice:
- Min-max maps each list onto
[0, 1]using its own minimum and maximum. Relative score fusion is Weaviate's name for min-max fusion, and it has been Weaviate's default hybrid method since v1.24. Min-max gets unstable when top scores cluster or the list is short, because tiny differences stretch across the whole range. - L2 divides each score by the list's L2 norm (OpenSearch
l2, Elasticsearchl2_norm). - Z-score standardizes each list by its per-query mean and standard deviation. Distribution-based score fusion (DBSF) is Qdrant's parameter-free variant: it normalizes each list against μ ± 3σ and sums the results. It handles a single outlier better than min-max, but its statistics are only as good as the top-k list they're computed from.

Re-ranking is not a third fusion method. It's a stage you add after fusing: the fused top-N gets re-scored by a more expensive model. Cross-encoders give the best precision on short passages (see our cross-encoder re-ranking guide). Late-interaction (ColBERT-style) models compare token vectors and cope better with long documents. Azure's "semantic hybrid search" works the same way: per Microsoft's docs, "Semantic ranking occurs after RRF merging of results."
| Method | Signal used | Tuning needed | Strengths | Failure modes |
|---|---|---|---|---|
RRF (k ≈ 60) |
Ranks only | Little (k, window size) |
Robust with no judgments, no calibration, cheap | Ignores confidence; a weak retriever's top ranks count as "agreement" |
| Weighted RRF | Ranks + per-retriever weight | Weights | Biases toward the stronger path | Still discards score gaps |
| Linear combination + min-max | Normalized scores | α (or weights) | Best accuracy when tuned; needs few labels | Unstable when top-k scores cluster or the list is short |
| Z-score / DBSF | Per-query score distribution | None (DBSF) or weights | Less sensitive to a single outlier | Statistics come only from the returned top-k |
| Late-interaction re-rank | Token-level MaxSim | Candidate pool size | Large gains over RRF at moderate cost | Needs token-level vectors |
| Cross-encoder re-rank | Joint query-document encoding | Model, top-N | Highest precision on short passages | Latency and GPU cost; truncation hurts long documents |
What the benchmarks say about RRF vs. linear combination
The most cited head-to-head is An Analysis of Fusion Functions for Hybrid Retrieval by Bruch, Gai and Ingber (ACM TOIS). A tuned convex combination beat RRF both in-domain and out-of-domain, and it was sample-efficient: α converged with less than 5% of their training data. The choice of normalizer barely matters, since learning the combination is "generally agnostic to the choice of score normalization." And RRF isn't parameter-free in practice: NDCG "swings wildly as a function of rrf parameters," and RRF tuned in-domain generalized poorly out of domain.
Balancing the Blend (Wang et al., PVLDB vol. 19) tested full-text, learned sparse, dense and multi-vector retrieval across 11 datasets and found what the authors call the weakest-link effect. On Touché, BM25 alone scored 0.650 nDCG@10, dense alone 0.390, and the RRF fusion of the two 0.604. Fusion did worse than the stronger retriever alone. Bigger candidate lists didn't fix it, and heavyweight re-rankers didn't fully recover the loss either.

Re-ranking fused candidates with late-interaction token vectors (their Tensor-based Re-ranking Fusion) took BM25 + dense on DBpedia from 0.668 with RRF to 0.722, an 8.1% gain. Cross-encoders struggled on long documents: on the MLDR dataset, input truncation dropped them below plain RRF, and they took over 100× longer to rank than the late-interaction approach. The authors also found that query length predicts which path is weak - semantic retrieval does better on longer, more descriptive queries.
Vendor benchmarks tell the same story once you read the tables. OpenSearch's RRF launch post is often quoted as saying RRF "consistently outperforms" normalization, but that phrase refers to latency. On relevance, RRF scored lower than score-based hybrid on all six BEIR datasets they tested: 3.86% lower NDCG@10 on average, for latency gains under 2%. A fine trade with no judgments, a poor one once you have them. RRF remains a strong baseline, though: a 2026 TREC-COVID study found it beat a newer projection-based fusion method on nDCG@10.
Which fusion method should you use?
Go through these in order:
- Measure each retriever alone. If one path scores far below the other on your queries, fusion will pull results toward it. Fix it, down-weight it, or route around it.
- No relevance judgments: use RRF. Set
k = 60and a window of at least 100 per retriever. You can ship it without any labels. - 50 to 200 judged queries: tune a linear combination. That range is our rule of thumb, not a number from the paper. Start with min-max, and try z-score or DBSF if a single outlier score flattens the rest of a list.
- Precision at the top matters: add a re-ranker over the fused top-N. Use a cross-encoder for short passages and late interaction for long documents.
- Query shapes differ: route. Weight lexical higher for short or identifier-like queries (SKUs, error codes), and dense higher for long natural-language questions.
- Embedding model, analyzer or corpus changed: re-tune. Weights fitted to the old score distributions are now stale.
For RAG, the LLM reads only the top 3 to 10 chunks, so recall at re-rank depth is what counts. We typically retrieve 100 to 200 candidates per path, fuse, and re-rank the top 50 to 100. LLM-generated queries run long, which favors the dense path, so check whether BM25 became your weak link.

Engine settings
| Engine | Rank-based | Score-based | Defaults to watch |
|---|---|---|---|
| Elasticsearch | rrf retriever, per-retriever weights GA in 9.2 |
linear retriever (8.18 / 9.0+), minmax or l2_norm (9.1+) |
rank_window_size defaults to 10; linear normalizer defaults to none |
| OpenSearch | score-ranker-processor (2.19+) |
normalization-processor: min_max, l2, z_score |
Weights must sum to 1; z_score only with arithmetic_mean |
| Qdrant | rrf (1.10+), configurable k (1.16+) |
dbsf (1.11+) |
k defaults to 2 with zero-based ranks |
| Weaviate | rankedFusion |
relativeScoreFusion (default since 1.24) |
Server alpha defaults to 0.75 |
| Azure AI Search | RRF, always on for parallel queries | Not available | Semantic ranker runs after RRF |
A tuned Elasticsearch linear retriever looks like this. Set the normalizer explicitly, because the default none adds raw BM25 to cosine similarity:
GET /products/_search
{
"retriever": {
"linear": {
"retrievers": [
{ "retriever": { "standard": { "query": { "match": { "title": "noise cancelling headphones" } } } },
"weight": 0.3, "normalizer": "minmax" },
{ "retriever": { "knn": { "field": "title_embedding", "query_vector": [0.42, -0.13, 0.88], "k": 100, "num_candidates": 200 } },
"weight": 0.7, "normalizer": "minmax" }
],
"rank_window_size": 100
}
}
}
In OpenSearch, the same fusion is a search pipeline on a hybrid query, with weights mapped to sub-queries by position. Or skip hand-tuning: the Search Relevance Workbench Hybrid Optimizer in 3.7 sweeps 82 variants per query, including z_score and RRF.
PUT /_search/pipeline/hybrid-minmax
{
"phase_results_processors": [
{ "normalization-processor": {
"normalization": { "technique": "min_max" },
"combination": { "technique": "arithmetic_mean", "parameters": { "weights": [0.3, 0.7] } }
} }
]
}
Pitfalls we see in audits
- Porting
kbetween engines.k = 60in Elasticsearch or OpenSearch isk = 61in Qdrant, which counts ranks from zero and defaults tok = 2. - Min-max over tiny windows. With Elasticsearch's default window of 10, min-max normalizes over ten scores and a mediocre document can land at 1.0.
- A fusion window smaller than the re-rank depth. Re-rank the top 100 but fuse only 50 per retriever, and the re-ranker never sees the documents it could have rescued.
- Tuning on the aggregate metric only. A blend that lifts average nDCG@10 can quietly break identifier lookups. Break results down by query class.
Frequently Asked Questions
Is RRF better than score normalization? Not once you can tune. Bruch et al. found a tuned convex combination beats RRF in-domain and out-of-domain, and OpenSearch's own benchmark had RRF 3.86% lower on NDCG@10. RRF is the better choice when you have no judged queries.
What is distribution-based score fusion (DBSF)? DBSF is Qdrant's score fusion method. For each query, it normalizes every retriever's scores using their mean and standard deviation, anchored at μ ± 3σ, then sums them. It has no parameters, so it's a zero-tuning alternative to RRF that still uses score magnitude.
What is relative score fusion? Relative score fusion is Weaviate's min-max fusion. In each result list the top score becomes 1 and the bottom becomes 0, and the normalized scores are combined using alpha. It has been Weaviate's default since v1.24.
Is hybrid search better than pure vector search for RAG? Usually. RAG traffic is full of product codes, error strings, function names and acronyms, and dense embeddings handle exact tokens poorly (our sparse vs. dense vectors guide explains why). The exception is a corpus where the lexical path measures far below dense. There, the weakest-link effect means fusing it in can cost you.
Key Takeaways
- No hybrid search fusion method wins everywhere. RRF is the safe default without judgments; a tuned linear combination usually beats it with them.
- Tuning the weight matters more than picking the normalizer. Default to min-max and use z-score or DBSF when outliers distort it.
- A weak retriever drags fused results below the strong one alone (0.650 to 0.604 on Touché). Measure each path before fusing.
- Re-ranking often moves quality more than the fusion choice: late interaction gained 8.1% over RRF on DBpedia.
- Check engine defaults before porting configs: Qdrant's zero-based
k, Elasticsearch's window of 10, OpenSearch's sum-to-one weights.
If you're choosing a fusion strategy for Elasticsearch or OpenSearch and want it backed by judged queries instead of defaults, talk to our search team.