Skip to content
Retrieval and search

BM25 keyword search

The decades-old scoring formula inside many search engines, and why repeating a word stops helping.

Basics · 6 steps

Step 1 of 6· Illustrative documents and collection counts; the BM25 and IDF maths is real (Lucene's form)

in one minute

BM25 is the formula many search engines use to rank documents by the words they share with your query. Each matching word earns points. Rare words earn more than common ones: “router” tells you more than “reset”. A word that appears several times earns more, but with quickly shrinking returns, so stuffing a page with one word stops paying. Long documents are marked down a little, because they contain many words just by being long. Add up the points and sort. BM25 needs no training and no GPU, runs on an index of which documents contain which words, and remains a hard baseline for newer methods to beat.

Why it matters for your product

BM25 is cheap, fast and explainable: you can always say why a document ranked where it did. BEIR, a benchmark of 18 retrieval datasets, found it a robust zero-shot baseline: reranking and late-interaction models scored best on average but at a high compute cost, while cheaper dense retrievers often underperformed. It also matches exact names, product codes and error messages word for word. For any retrieval project, build and measure a BM25 baseline first, then add embedding search and reranking where they beat it on your own queries.

For engineersShow the maths

score(D, Q) = Σ over query words t: IDF(t) × tf ÷ (tf + k1 × (1 − b + b × dl ÷ avdl))

For each query word, multiply its rarity weight by a saturating function of how often it appears, where k1 is scaled by the document's length relative to the average (dl is the document's length, avdl the average). Add up the words. Many versions also multiply by (k1 + 1), which scales every score equally and leaves the ranking unchanged.

Worked example: “router” (IDF 4.20) appears 4 times in an 80-word page, average length 100, with k1 = 1.2 and b = 0.75: 4 ÷ (4 + 1.2 × 0.85) = 0.80, so the word earns 4.20 × 0.80 ≈ 3.34 points.

IDF(t) = ln(1 + (N − n + 0.5) ÷ (n + 0.5))

N is the number of documents and n the number that contain the word. This is Lucene's form; the Robertson–Spärck Jones weight it comes from has no “1 +” and turns negative for words found in more than half the documents.

Worked example: Among 10,000 documents, a word found in 150 of them gets ln(1 + 9,850.5 ÷ 150.5) ≈ 4.20; a word found in 1,200 gets about 2.12.

tf ÷ (tf + k1) → 1 as tf grows

The saturation curve for a document of average length: the share of a word's IDF that its mentions earn.

Worked example: With k1 = 1.2, one mention earns 45% of the maximum, three earn 71%, ten earn 89% and twenty earn 94%: repetition quickly stops paying.

where it stops working

BM25 matches words, not meaning: it misses synonyms and paraphrases, and it treats a query as a bag of words, ignoring word order. Its k1 and b have to be set by hand or tuned on judged queries, and the best values differ between collections.

Key terms

The words you will hear

Inverted index

A lookup from each word to the documents that contain it and how often, so only documents sharing a query word are scored.
Where it came from

Primary sources

  1. 01The Probabilistic Relevance Framework: BM25 and BeyondRobertson, Zaragoza · 2009
  2. 02Okapi at TREC-3Robertson et al. · 1995
  3. 03BM25Similarity (Lucene 9.11.0 core API)Apache Lucene · 2024
  4. 04BEIR: A Heterogenous Benchmark for Zero-shot Evaluation of Information Retrieval ModelsThakur et al. · 2021

Want this working on your data?

We design and build the systems these ideas power: retrieval, agents, voice and the models behind them. Start with a free discovery call.