Document processing
Reciprocal rank fusion, explained
Reciprocal rank fusion merges ranked lists by adding 1/(60 + rank). The 2009 paper, why k is 60, why no normalization is needed, and how engines use it.
Oct 25, 202612 min read8 sources
Why it matters
Hybrid search merges a keyword list and a vector list, and the merge rule decides which passage a reader or a language model sees first and cites.
The short version
- 1RRF scores a document as the sum over input lists of 1/(k + rank), with k = 60 fixed in a 2009 pilot study where values from 10 to 100 changed mean average precision by less than 0.003.
- 2RRF uses ranks only, so a BM25 score with no upper limit and a cosine similarity between 0 and 1 never have to be put on one scale.
- 3Elasticsearch, OpenSearch, and Weaviate implement RRF with a constant of 60, and Azure AI Search documents 60 as a value that performs best; OpenSearch and Azure add per-list weights.
Reciprocal rank fusion (RRF) is a rule for merging several ranked lists of documents into one list. Each document gets the sum, over every list it appears in, of 1 divided by a constant plus its rank in that list. Cormack, Clarke, and Büttcher presented it at SIGIR 2009, held July 19-23, 2009, in Boston, in a paper titled "Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods". Hybrid search systems adopted it because it merges a keyword list and a vector list without ever comparing their scores. This post covers the formula, the constant 60, the reason no normalization is needed, the implementations in Elasticsearch, OpenSearch, Weaviate, and Azure AI Search, the weighted variants, and the limits.
The RRF formula
The paper defines the score over a set D of documents and a set R of rankings, each a permutation of the documents:
RRFscore(d) = the sum over every ranking r in R of 1 / (k + r(d)),
where r(d) is the rank of document d in ranking r, counted from 1, and k = 60. The authors themselves call the formula naive. The Elasticsearch documentation writes the same rule as pseudocode: start at zero, and for each query whose result set contains the document, add 1.0 / (k + rank). A document absent from a list gets nothing from that list, a point the OpenSearch documentation makes explicit.
The arithmetic is small enough to do by hand. With k = 60:
| Position in list A | Position in list B | RRF score |
|---|---|---|
| 1 | 1 | 1/61 + 1/61 = 0.0328 |
| 1 | 3 | 1/61 + 1/63 = 0.0323 |
| 2 | 2 | 1/62 + 1/62 = 0.0323 |
| 1 | absent | 1/61 = 0.0164 |
| 10 | 10 | 1/70 + 1/70 = 0.0286 |
| 1 | 100 | 1/61 + 1/160 = 0.0226 |
A document ranked 10th in both lists outscores a document ranked first in one list and missing from the other. Agreement between lists counts for more than a single first place, and that is the behavior hybrid search wants: a passage that both the keyword engine and the vector engine rate highly is a safer top result than a passage only one of them likes.
Why k is 60
The constant has one job. The authors write that highly ranked documents matter more, but that the importance of lower-ranked documents should not vanish, as it would under an exponential decay. The constant k, in their words, mitigates the impact of high rankings by outlier systems: with k = 60, a first place is worth 1/61 and a tenth place 1/70, about 13% less, so a single system's first place carries limited weight on its own.
The value came from a pilot study. The authors fused the results of 30 configurations of their Wumpus search system on four TREC collections and varied k. On TREC topics 351-400, mean average precision (MAP) was .2072 at k = 0, .2123 at 10, .2134 at 20, .2139 at 30, .2138 at 40, .2144 at 50, .2145 at 60, .2146 at 70, .2147 at 80, .2145 at 90, .2142 at 100, and .2098 at 500. The best single system scored .2016, Condorcet Fuse .2074, and CombMNZ .2039. The authors fixed k = 60 during the pilot and did not alter it during the later validation, calling it near-optimal but not critical. Everything from 10 to 100 lay within .0024 of the best value, which is why implementations ship 60 as a default rather than as a tuned setting.
The implementations describe the constant's effect in the same terms. Elasticsearch's rank_constant must be at least 1 and defaults to 60; a higher value gives lower-ranked documents more influence. The OpenSearch score ranker processor accepts rank_constant from 1 to 10,000 with a default of 60, and its documentation says a larger constant makes scores more uniform and a smaller one gives more weight to top-ranked items. The Azure AI Search documentation says experiments show the algorithm "performs best when you set k to a small value, such as 60" and warns that this k is unrelated to the k that sets the number of nearest neighbors in a vector query.
Why RRF needs no score normalization
A BM25 score and a vector similarity measure different things on different scales. The Azure documentation's table of score ranges puts it plainly: a full-text BM25 score has no upper limit, a cosine similarity from the vector index falls between 0.333 and 1.00, and Euclidean and dot-product similarities fall between 0 and 1. Adding a BM25 score of 12.4 to a cosine of 0.87 would let the keyword side decide everything. The usual fix is to normalize each list's scores, for example by scaling the top score to 1 and the bottom to 0, and then take a weighted sum, but the scaling depends on the particular result set, and the OpenSearch documentation notes that min-max and L2 normalization are sensitive to outliers.
RRF skips the problem. The 2009 paper says RRF "combines ranks without regard to the arbitrary scores" returned by the individual methods, a property it shares with Condorcet Fuse, and that RRF needs no special voting algorithm or global information: ranks can be computed and summed one system at a time, so the rankings never have to be held in memory together. A rank of 1 means the same thing in a BM25 list and a vector list. The Elasticsearch documentation summarizes the consequence in four words: "RRF requires no tuning". The OpenSearch documentation lists the cases where that matters most: lists whose scores sit on scales that cannot be compared, data with outliers or high score variance, sparse relevance signals, and data that changes continuously, where score-based normalization would need recalibration and RRF does not.
The method's two 2009 competitors show what RRF avoids. CombMNZ needs a score function for every system and a cutoff rank; it multiplies the sum of the uncalibrated scores by the number of systems that ranked the document inside the cutoff, and the authors conjecture that its higher variance comes from some systems' scores being more amenable than others. Condorcet Fuse sorts documents by majority vote over pairwise preferences, and the authors argue that a simple majority of weak preferences can overrule substantially stronger ones, whereas under RRF one or two systems that rank a document highly can lift it substantially.
What the 2009 paper measured
After the pilot, the authors fused actual TREC submissions. MAP for RRF against the best individual run, Condorcet Fuse, and CombMNZ was .3686 against .3586, .3652, and .3575 on the TREC 2004 Robust track; .4350 against .4226, .4256, and .4381 on TREC 3; .3394 against .3165, .3213, and .3237 on TREC 5; and .2830 against .3519, .2750, and .2671 on TREC 9. The TREC 9 best run was a manual, human-in-the-loop submission; the best automated run scored .2801, below RRF. Across the pilot and TREC experiments the authors put RRF's margin over Condorcet, CombMNZ, and the best system at 4% to 5% on average, with sign tests giving p of about 0.008 against Condorcet and about .04 against CombMNZ.
A third experiment fused the baseline learning-to-rank methods supplied with the LETOR 3 dataset, 583,850 document-query pairs. RRF scored 0.6051 MAP, against 0.5917 for Condorcet, 0.5846 for ListNet, 0.5778 for AdaRank, 0.5737 for RankSVM, and 0.5622 for RankBoost; CombMNZ edged RRF at 0.6107, a difference the authors report as not significant (p about .2). RRF beat every individual learned ranker, the best by 0.02, or 4%. The authors note that MAP alone is reported for brevity and that precision at k, R-precision, and nDCG gave comparable results.
Two things about the evidence matter for anyone citing it. The fused systems were many, 30 configurations in the pilot and full sets of TREC submissions afterward, not the 2 lists of a typical hybrid search. And the paper reports no experiment with a keyword list and a dense vector list, which did not exist in 2009. The hybrid use is an application of the method, not a result from the paper.
How hybrid search systems use RRF
Four production systems document their implementations.
Elasticsearch exposes RRF as the rrf retriever. The parameters are rank_constant, default 60, and rank_window_size, which sets how many results each sub-query contributes and defaults to the request's size; a larger window improves relevance at a cost in performance. The documentation lists limits: the rrf retriever does not support scroll, sort, or rescore, highlighting on vector fields is unsupported, and the older sub-search syntax has been replaced by the retriever API.
OpenSearch added RRF in version 2.19 through the score-ranker-processor, a search-phase results processor that runs between the query and fetch phases with technique set to rrf. The documentation contrasts it with the normalization processor, available since 2.10, which combines normalized scores (min_max, l2, or z_score) with an arithmetic, geometric, or harmonic mean. The rank-based processor discards score magnitudes; the score-based one preserves them. The same page reports a benchmark on six BEIR datasets in which RRF averaged 3.86% lower nDCG@10 than the score-based pipeline, with comparable latency and coordinator CPU use, and recommends RRF as the starting point when the score distributions have not been measured.
Weaviate offers two fusion algorithms for its hybrid query. The concepts page describes rankedFusion, in which each object is scored 1/(rank + 60) in each result list and the scores added, as the default through version 1.23, and relativeScoreFusion, in which each list's scores are normalized so the highest becomes 1 and the lowest 0 before a weighted sum, as the default from version 1.24. The alpha parameter sets the weight of the vector side, from 0 for keyword only to 1 for vector only, with a server default of 0.75; the how-to page warns that the effective weighting depends on the client when alpha is not set, and the concepts page recommends setting alpha explicitly.
Azure AI Search applies RRF whenever more than one query executes in parallel: a full-text query plus a vector query is 2 executions, a full-text query plus 2 vector queries over 5 vector fields is 11. The engine assigns each document 1/(rank + k) per list, sums the values, and sorts. The fused score's upper bound is set by the number of queries fused, each contributing at most about 1/k, so merging 3 queries produces higher scores than merging 2. By default a hybrid query returns the top 50 matches of the fused result set, and the text side is capped at 1,000 matches, a limit that maxTextRecallSize can raise from its default of 1,000.
Weighted RRF variants
The 2009 formula weights every list equally. Two implementations add weights. OpenSearch's score-ranker-processor accepts a weights array under combination.parameters, one floating-point value between 0.0 and 1.0 per query clause, which must sum to 1.0; with no array, all clauses weigh the same. The documentation's example sets rank_constant to 40 and weights of 0.7 and 0.3 for a keyword clause and a neural clause. Azure AI Search applies a vector weighting multiplier to each vector query's reciprocal rank score before the sum: the default of 1.0 leaves the score as is, 0.5 reduces that list's influence, and 2.0 increases it. In the documentation's worked example, a document at position 1 in one vector list, position 5 in a second, and position 10 in the BM25 list has its first vector score halved and its second doubled before the three are added.
Weaviate's relativeScoreFusion is a weighted sum of normalized scores rather than of reciprocal ranks, and sits closer to what Bruch, Gai, and Ingber studied. Their paper, submitted October 21, 2022 and revised May 4, 2023, examined fusion by a convex combination of lexical and semantic scores. They found that learning the combination weight is generally agnostic to the choice of score normalization, that the method is sample efficient, requiring only a small set of training examples to tune its single parameter to a target domain, and, contrary to existing studies, that RRF is sensitive to its parameters. A weight on the keyword list is the natural way to favor exact identifiers such as part numbers, and a weight on the vector list the natural way to favor paraphrase; the implementations above make either possible, but the 2009 paper supplies no guidance on the values.
The limits of RRF
RRF throws away information. A document that beats the next one by a tiny margin and a document that beats it by a wide margin get the same reciprocal rank, a point the OpenSearch documentation makes when comparing its two processors. Weaviate's worked example shows the consequence: with five objects, ranked fusion gives each rank the same score regardless of the raw values and puts object 2 first, while relative score fusion, which keeps the margins, puts object 1 first because it was the standout keyword match and still sat in the top vector group. Neither answer is wrong; they encode different assumptions about whether the scores mean anything.
RRF also inherits the recall of its inputs. Only documents inside each list's window are fused, so Elasticsearch's rank_window_size and the top-k of each vector query bound what can appear, and a document that neither retriever returned cannot be rescued. The constant 60 flattens the top of each list: a tenth place is worth only about 13% less than a first place, so RRF is poor at preserving a retriever's confidence that its top result is far better than its second. The 2009 pilot found k uncritical between 10 and 100 for fusing 30 similar systems; Bruch, Gai, and Ingber found the method sensitive to its parameters when fusing a lexical and a semantic list, and found a tuned convex combination better in and out of domain. OpenSearch's own benchmark put the cost of rank-only fusion at 3.86% of nDCG@10 on six BEIR datasets. RRF is the method to use when no labeled queries exist to tune anything else, and the method to measure against once they do.
What to check
- Which fusion rule merges the keyword and vector lists, RRF or a weighted sum of normalized scores, and what is the constant k or the weight?
- How many results does each retriever contribute to the fusion, and can a relevant document fall outside that window?
- Are the lists weighted, and if so, were the weights set from labeled queries on these documents or left at the defaults?
- Were the retrievers' own scores inspected before choosing rank-only fusion, or was RRF chosen because the scores were never compared?
- When a top result is cited, is it possible to see its rank in each input list, so a disagreement between the keyword and vector sides is visible?
Azcuna's TRACE is one offline viewer for S1000D, MIL-STD-3001 XML, and PDF technical manuals. It keeps the source location and the markings of everything it shows and never modifies the source. It was proposed to NAVAIR under Navy SBIR Phase I topic DON26BZ05-NV078, and the proposal was submitted on September 23, 2026.
Questions people ask
What is reciprocal rank fusion?
Reciprocal rank fusion (RRF) is a method for merging several ranked lists of documents into one. Cormack, Clarke, and Buettcher presented it at SIGIR 2009 in Boston. Each document's fused score is the sum, over every list it appears in, of 1 divided by (k plus its rank in that list), with k set to 60. Documents that rank well in several lists score highest. The paper reported that RRF beat the best single system and two established fusion methods, Condorcet Fuse and CombMNZ, by 4% to 5% on average.
What is the RRF formula?
The 2009 paper gives RRFscore(d) as the sum over all rankings r of 1 / (k + r(d)), where r(d) is the document's rank in that list, counted from 1, and k = 60. A document missing from a list contributes nothing for that list, and the Elasticsearch documentation shows the same rule as pseudocode. A document ranked first in two lists scores 2/61, about 0.0328; a document ranked first in one list and absent from the other scores 1/61, about 0.0164.
Why is k 60 in reciprocal rank fusion?
Cormack, Clarke, and Buettcher fixed k = 60 during a pilot study that fused 30 configurations of their Wumpus search system on four TREC collections. Their table shows mean average precision of .2072 at k = 0, .2145 at k = 60, .2147 at k = 80, and .2098 at k = 500; they call 60 near-optimal and the choice not critical. The constant keeps a single system that ranks a document first from dominating the sum, and Elasticsearch and OpenSearch use 60 as the default.
Why does RRF not need score normalization?
Because it never reads the scores. The 2009 paper says RRF combines ranks without regard to the arbitrary scores returned by particular ranking methods, and that ranks can be summed one system at a time with no global information. The Azure AI Search documentation lists the ranges that would otherwise have to be reconciled: a BM25 score has no upper limit, while a cosine similarity falls between 0.333 and 1.00. A rank of 1 means the same thing in both lists, so no scaling step is needed.
How is RRF used in hybrid search?
A hybrid search runs a keyword query and a vector query, takes the top results of each, and fuses the two ranked lists with RRF. Elasticsearch offers an rrf retriever with rank_constant defaulting to 60 and rank_window_size setting how many results each sub-query contributes. OpenSearch 2.19 added a score-ranker-processor with technique rrf and the same default constant. Weaviate's rankedFusion scores each object 1/(rank + 60) in each list. Azure AI Search applies RRF whenever two or more queries run in parallel, including multiple vector queries.
What is weighted RRF?
Weighted RRF multiplies each list's reciprocal rank contribution by a weight before summing. The OpenSearch score-ranker-processor takes a weights array, one value between 0.0 and 1.0 per query clause, summing to 1.0, with equal weights if none is given. Azure AI Search applies a vector weighting multiplier to each vector query's reciprocal rank score; the default 1.0 leaves it unchanged, 0.5 halves its influence, and 2.0 doubles it. The 2009 paper itself describes only the unweighted sum.
What are the limits of reciprocal rank fusion?
RRF discards how far apart the scores were. The OpenSearch documentation notes that a document that outscores the next result by a small margin is treated the same as one that outscores it by a large margin, and reports that on six BEIR datasets RRF averaged 3.86% lower nDCG@10 than its score-based hybrid pipeline. Only documents inside each list's window are fused, so a document neither retriever returned cannot appear. Bruch, Gai, and Ingber found RRF sensitive to its parameters, contrary to earlier studies.
Is RRF better than a weighted sum of scores?
Not always. Bruch, Gai, and Ingber's study, An Analysis of Fusion Functions for Hybrid Retrieval, revised in May 2023, found RRF sensitive to its parameters and found a convex combination of normalized lexical and semantic scores sample efficient, needing only a small set of training examples to tune its one parameter. RRF needs no training examples, which is why the 2009 authors built it as an unsupervised baseline. With labeled queries a tuned weighted sum can do better; without them, RRF is the safer default.
Sources
- 1Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods · Cormack, Clarke, and Büttcher (SIGIR 2009), University of Waterloo copy
- 2Reciprocal rank fusion · Elasticsearch Guide
- 3Reciprocal rank fusion · OpenSearch Documentation
- 4Score ranker processor · OpenSearch Documentation
- 5Hybrid search (concepts) · Weaviate Documentation
- 6Hybrid search (how-to) · Weaviate Documentation
- 7Hybrid Search Scoring (RRF) - Azure AI Search · Microsoft Learn
- 8An Analysis of Fusion Functions for Hybrid Retrieval · arXiv (Bruch, Gai, and Ingber; revised May 2023)
Where this shows up in our work
- TRACE, the offline S1000D and IETM viewer opens S1000D, MIL-STD-3001 and PDF technical manuals on a tablet with every marking intact.
- BABEL, offline multilingual translation and search translates and searches foreign-language documents on-device, every fact tied to its source passage.
