<!-- generated by build_articles.py — edit content/science/reciprocal-rank-fusion.md instead -->
---
title: "Reciprocal rank fusion formula"
canonical: "https://xerj.org/science/reciprocal-rank-fusion"
updated: "2026-11-14"
source: "content/science/reciprocal-rank-fusion.md"
---

# Reciprocal rank fusion formula

**Short answer** (updated 2026-11-14): What is the reciprocal rank fusion formula? For each list an item appears in, add 1 / (k + rank), then add those values. The lists do not need a shared score scale. Cormack, Clarke and Buettcher found k = 60 near-optimal in their 2009 pilots. XERJ uses k = 60 by default and accepts another value.

**TL;DR** Reciprocal rank fusion merges two or more ranked lists by adding 1 / (k + rank) for each list an item appears in. The lists do not need a shared score scale.

## Agent prompt

```text
Act as a coding agent. Read https://xerj.org/llms.txt, install XERJ, start a local node, index one folder I point you to, and run one search so I can see a cited passage.
```

*Figure: The formula and the choice k = 60 come from Cormack, Clarke and Buettcher, Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods, SIGIR 2009. The three documents are a teaching example, not a XERJ run.*

## How it works

You start with two or more ranked lists, for example a BM25 list and a vector list. For each document, look up its rank in each list. Add 1 / (k + rank) for every list it appears in. Missing from a list means that list adds nothing. Sort by the total.

The table above is a labeled example with three documents and k = 60. It is not a measurement on a XERJ corpus. In that example, a document that ranks first in one list and second in the other ties with a document that does the reverse. A document that appears in only one list ranks lower.

k is a constant that softens the gap between early and later ranks. The 2009 paper reports k = 60 as near-optimal in the authors' pilots.

## The formula

The score for a document is the sum, over every ranked list it appears in, of:

`score(d) = 1 / (k + rank_i(d))`

`rank_i(d)` is the 1-based rank of `d` in list `i`. If the document is missing from a list, that list adds nothing. `k` is a constant. A larger `k` flattens the gap between rank 1 and later ranks. In their 2009 pilots, Cormack, Clarke and Buettcher found `k = 60` near-optimal. That value is also the published XERJ default.

The table above is a labeled example, not a measurement on a XERJ corpus. Here is the same example in Python:

```python
# Example only, not a XERJ measurement.
# k = 60 comes from Cormack, Clarke and Buettcher, SIGIR 2009.

def rrf_score(ranks, k=60):
    return sum(1.0 / (k + rank) for rank in ranks)

# Document X ranks 1 in list A and 2 in list B:
print(round(rrf_score([1, 2]), 4))  # 0.0325
```

## How XERJ uses it

XERJ uses reciprocal rank fusion to merge a lexical arm with a vector arm in [hybrid search](/science/hybrid-search). The product default is k = 60, and the request can set another value. A weighted linear sum is also available when you want to keep raw scores, after normalization.

The practical guide is [when to use reciprocal rank fusion](/answers/reciprocal-rank-fusion-when-to-use). The request shape is in [how to run hybrid search in XERJ](/answers/what-is-hybrid-search).

## History and research

The method was introduced by Cormack, Clarke and Buettcher, [Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods](https://cormack.uwaterloo.ca/cormacksigir09-rrf.pdf), SIGIR 2009, pages 758 to 759. An ACM page also lists the paper at [doi 10.1145/1571941.1572114](https://dl.acm.org/doi/10.1145/1571941.1572114).

The k = 60 figure on this page is theirs, from those pilots. It is also the published XERJ default. This page does not add a new fusion experiment.

## Guides

See [when to use reciprocal rank fusion](/answers/reciprocal-rank-fusion-when-to-use), [how XERJ combines search](/answers/how-xerj-combines-search) and the [hybrid search recipe](/docs/recipes/hybrid-search).

## Related terms

[Hybrid search](/science/hybrid-search), [BM25](/science/bm25), and [semantic search](/science/semantic-search).

## FAQ

### What is the reciprocal rank fusion formula?

For each list an item appears in, add 1 / (k + rank). Then add those values. A common choice of k is 60, from the 2009 paper.

### Why use ranks instead of raw scores?

BM25 scores and vector similarities sit on different scales. Ranks do not, so you can fuse the lists without a shared unit.

### What does the constant k do?

A larger k flattens the gap between rank 1 and later ranks. In their 2009 pilots, Cormack, Clarke and Buettcher found k = 60 near-optimal. XERJ uses k = 60 by default and accepts another value.

### How does XERJ use RRF?

As the usual fusion method in hybrid search. The how-to, and when to pick a weighted sum instead, is the hybrid search answer and the when-to-use RRF answer.

## Related

- [What is hybrid search?](/science/hybrid-search)
- [What is Reciprocal Rank Fusion?](/answers/reciprocal-rank-fusion-when-to-use)
- [How to run hybrid search in XERJ](/answers/what-is-hybrid-search)
- [How does XERJ combine BM25 and kNN?](/answers/how-xerj-combines-search)
- [What is agentic memory?](/science/agentic-memory) (same intent: Science)
- [BM25 vs vector search](/science/bm25) (same intent: Science)
- [What is context engineering?](/science/context-engineering) (same intent: Science)
