PGPradhumn Gupta
← Writing

BM25 vs BM42 vs miniCOIL vs SPLADE: Which Sparse Retriever for Hybrid RAG?

BM25 is lexical, SPLADE learns term expansion, and Qdrant's BM42/miniCOIL add neural weights to the BM25 formula—compared for hybrid RAG.

Contents

Short answer: BM25 is classic lexical scoring (term frequency + inverse document frequency, no model). SPLADE is a learned-sparse retriever that expands each token into related vocabulary terms with learned weights. BM42 and miniCOIL are Qdrant-built sparse neural retrievers that keep the BM25 scoring formula but replace its statistical term weights with transformer-derived ones—miniCOIL is the one Qdrant recommends for new projects. None of them should be used alone in production; pair whichever you pick with dense embeddings.

Quick comparison

BM25SPLADE (prithivida/Splade_PP_en_v1)BM42miniCOIL
TypeStatisticalLearned sparse (MLM expansion)Neural weights on BM25Neural weights on BM25
Term importanceIDF + saturationLearned per-term logitsAttention-basedContextual, per-token
VocabularyCorpus tokens onlyExpands to related termsQuery/doc tokensQuery/doc tokens
Out-of-domainRobust (no training)Can degrade on unseen domainsRobust-ishRobust-ish
Vector sizeSmallLarge (many expansion terms)SmallSmall
Inference costNone (index-time only)Transformer forward passTransformer forward passLightweight transformer
Cold startInstantNeeds model + heavy indexingModel downloadModel download

How each handles term importance, vocabulary, and OOD terms

BM25 scores a document purely on how often query terms appear, discounted by how common those terms are across the corpus. It never leaves the observed vocabulary, which is exactly why it's bulletproof on out-of-domain and rare terms—a product SKU, an error code, or a surname is matched literally. Its weakness is that it can't tell that "cardiac" and "heart" are related.

SPLADE fixes vocabulary mismatch by running a masked-language-model head over the text and expanding each token into a weighted bag of related terms. That gives strong recall, but the expansion inflates the vector and the learned weights can drift on domains far from the training data.

BM42 and miniCOIL take a middle path: keep BM25's proven ranking formula, but derive term importance from a transformer instead of raw frequency. BM42 uses attention weights; miniCOIL learns compact contextual weights per token. They don't expand vocabulary aggressively like SPLADE, so vectors stay small and behavior stays close to lexical—more predictable out of domain.

Index size, inference cost, cold start

  • BM25: cheapest everywhere. No model, no GPU, near-instant to stand up. Cost is only the inverted index.
  • SPLADE: largest vectors (expansion terms) and a transformer forward pass at both index and query time. Indexing a big corpus is slow and storage-heavy.
  • BM42 / miniCOIL: small vectors like BM25, plus a model forward pass at ingest and query. miniCOIL's model is deliberately lightweight, so its query-time latency is closest to BM25 among the neural options.

Which to pick by corpus and latency budget

  • Keyword-heavy, exact-match corpora (code, logs, IDs, legal citations) with a tight latency budget: BM25. It's hard to beat on literal matching and adds zero inference cost.
  • New hybrid project, general prose, want better-than-lexical without SPLADE's overhead: miniCOIL. This is Qdrant's default recommendation for new work.
  • Short or technical text where BM25's frequency stats are noisy: BM42.
  • Max learned-sparse recall, willing to pay for larger vectors and slower indexing: SPLADE.

How each plugs into hybrid + rerank

The pattern is identical regardless of which sparse retriever you choose. Run sparse and dense in parallel, fuse, then rerank the merged shortlist.

# Qdrant hybrid query: dense + sparse (miniCOIL/BM42/SPLADE), fused, then rerank
results = client.query_points(
    collection_name="docs",
    prefetch=[
        Prefetch(query=dense_vec,  using="dense",  limit=40),
        Prefetch(query=sparse_vec, using="sparse", limit=40),  # sparse retriever output
    ],
    query=FusionQuery(fusion=Fusion.RRF),  # reciprocal rank fusion
    limit=40,
)
# then: cross-encoder rerank the 40 → keep top 8 for the LLM

Sparse-only retrieval consistently underperforms in production because it can't capture semantic similarity that shares no tokens. Dense-only misses exact terms. The sparse retriever's job in the stack is precise lexical recall; the dense vector covers semantics; the reranker fixes ordering. Swapping BM25 for miniCOIL or SPLADE changes the sparse leg only—the fusion and rerank stages stay the same.

Pick miniCOIL for a new hybrid RAG build, keep BM25 for pure keyword workloads, reach for SPLADE only when you need its recall and can pay for it—and never ship any of them without dense vectors and a reranker.

Related: more writing.

Frequently asked

What's the difference between BM25, BM42, miniCOIL, and SPLADE?
BM25 is statistical lexical scoring. SPLADE learns to expand tokens into related vocabulary. BM42 and miniCOIL keep BM25's formula but replace frequency-based term weights with transformer-derived ones.
Is BM42 better than BM25?
BM42 adds transformer attention-based term weighting on top of BM25's formula, helping short and technical text, but you should still pair it with dense vectors.
What is miniCOIL?
A lightweight sparse neural retriever from Qdrant that learns contextual term weights on the BM25 formula. It's Qdrant's recommended sparse retriever for new projects.
Is SPLADE still worth using?
Yes for strong learned-sparse recall, but it has larger vectors and higher indexing and query cost than miniCOIL or BM42. The common model is prithivida/Splade_PP_en_v1.
ShareXLinkedIn

Keep reading

Get new essays by email

Occasional field notes on production RAG and LLM systems. No spam, unsubscribe anytime.

Written by Pradhumn Gupta.

If this was useful, I share more on LinkedIn.