Home » RAG Pipelines » Hybrid Search for RAG

Hybrid Search for RAG: Combining Vector and Keyword Retrieval

Hybrid search combines dense vector retrieval (semantic similarity) with sparse keyword retrieval (BM25 or TF-IDF) and merges the results using a fusion algorithm, most commonly Reciprocal Rank Fusion. This approach consistently outperforms either method alone across RAG benchmarks because it covers both failure modes: dense retrieval misses exact keyword matches while sparse retrieval misses semantic connections, and the combination captures both.

Why Dense or Sparse Alone Is Not Enough

Dense retrieval, where you embed both the query and documents into the same vector space and find the nearest neighbors, is excellent at understanding meaning. A query about "reducing customer churn" retrieves documents about "retention strategies" and "preventing subscriber loss" even though those phrases share no common terms. This semantic matching is why vector search became the default retrieval method for RAG pipelines. But dense retrieval has a fundamental weakness: it struggles with exact matches. A query for "error code E-4217" gets mapped into a general "error handling" region of the embedding space, and the system may return documents about error handling in general rather than the one document that mentions that specific code.

Sparse retrieval using BM25 has the opposite profile. BM25 scores documents by term frequency, inverse document frequency, and document length normalization. It excels at precise keyword matching: "error code E-4217" reliably retrieves any document containing that exact string. BM25 also handles rare terminology, product names, acronyms, and domain-specific jargon that embedding models may not have seen during training. But BM25 cannot bridge vocabulary gaps. "Reducing churn" and "retention strategies" share zero terms, so BM25 assigns zero relevance between them. It also cannot handle typos, abbreviations, or paraphrases that are semantically identical but lexically different.

The failure modes are complementary. Dense retrieval fails on exact matches and rare terms. Sparse retrieval fails on semantic connections and paraphrasing. A system that combines both covers the weaknesses of each. This is not a theoretical advantage: benchmarks across BEIR, MTEB, and production RAG evaluations consistently show that hybrid retrieval produces 5% to 15% higher recall@10 and NDCG@10 compared to the stronger of the two individual methods, and the improvement is largest on queries where one method alone would fail.

How Reciprocal Rank Fusion Works

The standard algorithm for combining dense and sparse result lists is Reciprocal Rank Fusion (RRF). RRF was introduced by Cormack, Clarke, and Buettcher in 2009 and remains the default fusion method in 2026 because it is simple, parameter-light, and robust across diverse query types.

The algorithm works as follows. Each retrieval method produces a ranked list of results. For each result in each list, RRF assigns a score of 1 / (k + rank), where k is a smoothing constant (typically 60) and rank is the result's position in that list (1-indexed). If a result appears in both lists, its scores are summed. The final merged list is sorted by the combined RRF score in descending order.

The k constant controls how much weight is given to the top-ranked results versus lower-ranked ones. A smaller k (say 10) concentrates score heavily on the top few results, making the fusion more sensitive to each method's top pick. A larger k (say 100) flattens the score distribution, giving more equal weight across all positions. The original paper used k=60, and this value works well enough in practice that most implementations use it without tuning. If you do tune it, evaluate on your specific query distribution: domains with short, precise queries (like error codes or product IDs) may benefit from a smaller k that emphasizes keyword matching, while domains with longer, conceptual queries may prefer the default.

The key advantage of RRF over other fusion methods (like linear score combination) is that it operates on ranks rather than raw scores. Dense and sparse retrieval produce scores on completely different scales: cosine similarity ranges from -1 to 1, while BM25 scores have no fixed range and depend on corpus statistics. Normalizing these scores for direct combination is unreliable because the score distributions change with different queries. RRF sidesteps this entirely by using only the ordinal position of each result, making it calibration-free. The existing explanation of reciprocal rank fusion covers the mathematical details and edge cases.

BM25 Implementation Options

Adding BM25 to an existing dense retrieval pipeline requires a keyword search index alongside your vector index. The implementation depends on your database.

PostgreSQL with pgvector is the simplest path because PostgreSQL has built-in full-text search. Create a tsvector column on your chunks table, populate it with to_tsvector() during ingestion, create a GIN index, and query with ts_rank() and to_tsquery(). Run the vector similarity search and the full-text search as two separate queries, collect both result sets, and apply RRF in application code. This requires no additional infrastructure: one database handles both dense and sparse retrieval.

Qdrant supports hybrid search natively since version 1.7. When creating a collection, define both a dense vector field and a sparse vector field. During ingestion, store the dense embedding in the vector field and a BM25-like sparse representation (using SPLADE or a bag-of-words encoding) in the sparse field. At query time, send both a dense query vector and a sparse query vector, and Qdrant performs RRF internally. This is the cleanest implementation because the database handles fusion with no application-level merging.

Weaviate also supports hybrid search natively with a configurable alpha parameter that controls the weight between BM25 and vector search. An alpha of 0 uses pure BM25, 1 uses pure vector, and 0.5 gives equal weight. Weaviate stores both representations automatically during ingestion, so adding hybrid search requires only changing the query from nearVector to hybrid.

Elasticsearch / OpenSearch with the k-NN plugin supports both BM25 and approximate nearest neighbor search in a single query. You define a knn field for the vector and use the standard text fields for BM25. The k-NN results and BM25 results are merged using a configurable combination. This is a strong option if your organization already runs Elasticsearch for other purposes.

Pinecone added sparse-dense vector support in 2024. You upload both a dense vector and a sparse vector (from SPLADE or a BM25 encoding) for each record, and query with both simultaneously. Pinecone handles the fusion internally. The implementation requires generating sparse vectors client-side, since Pinecone does not compute them.

Sparse Vector Encoders: BM25 vs SPLADE

Traditional BM25 operates on term frequencies within a pre-built inverted index. It is simple, fast, and well-understood, but it requires full-text search infrastructure. For databases that support sparse vectors natively (Qdrant, Pinecone, Milvus), you can encode the BM25-style signal as a sparse vector instead, where each dimension corresponds to a vocabulary term and the value is the BM25 weight for that term in the document.

SPLADE (Sparse Lexical and Expansion) takes this further by using a trained neural model to produce sparse representations. Unlike raw BM25 encoding, SPLADE expands the vocabulary: a document about "machine learning" might produce non-zero weights for "AI," "training," "neural network," and other related terms that do not appear literally in the text. This expansion bridges some of the vocabulary gap that pure BM25 misses, making SPLADE sparse vectors a midpoint between sparse and dense retrieval.

In practice, the choice depends on your infrastructure. If your database supports full-text search (PostgreSQL, Elasticsearch), use native BM25 because it requires no additional model inference. If your database supports sparse vectors but not full-text search (Qdrant, Pinecone), encode with SPLADE for better quality or with a simple bag-of-words encoder for lower latency. SPLADE adds 10 to 30 milliseconds of model inference per query, which matters at high throughput but is negligible for most RAG applications.

Weighting and Tuning Hybrid Search

The relative weight of dense versus sparse retrieval affects which types of queries benefit most. Equal weighting (50/50) is a reasonable default, but the optimal balance depends on your query distribution.

If your users frequently search for specific identifiers, product names, error codes, or exact phrases, increase the sparse weight. A 60/40 or 70/30 split favoring sparse retrieval ensures that exact matches dominate when they exist. If your users ask conceptual, open-ended questions that require understanding intent rather than matching terms, increase the dense weight. A 70/30 split favoring dense retrieval prioritizes semantic understanding.

The best way to determine the optimal weighting is to evaluate on your own query set. Build a test set of 50 to 100 queries with known relevant documents, run retrieval at different weight combinations, and measure recall@5 and NDCG@10 at each point. In practice, most RAG applications land between 40% and 60% dense weight, and the difference between 45% and 55% is small enough that the default of 50/50 works without tuning.

Some implementations use query-dependent weighting, where a classifier examines the query and adjusts the weights dynamically. Short queries with specific identifiers get more sparse weight; longer conceptual queries get more dense weight. This adds complexity and is only worthwhile if your query distribution is highly bimodal (mixing exact lookup queries with conceptual questions in the same system). For most RAG applications, static weights are sufficient.

Hybrid Search and Reranking

Hybrid search and reranking are complementary stages, not alternatives. Hybrid search improves recall: it increases the probability that the correct document appears somewhere in the candidate set. Reranking improves precision: it moves the correct document to the top of the list. The combination, where hybrid retrieval produces 20 candidates and a cross-encoder reranker selects the top 3 to 5, is the strongest retrieval configuration available for RAG in 2026.

The practical pipeline is: embed the query (dense), encode the query (sparse), run both searches in parallel, merge with RRF, take the top 20 candidates, pass them through the reranker, take the top 3 to 5, and feed them to the LLM. The total retrieval latency is dominated by the slowest of the parallel searches (typically dense search at 5 to 20 milliseconds) plus the reranker (50 to 200 milliseconds), for a total of 60 to 220 milliseconds. This is well within acceptable limits for a RAG system where the LLM generation step takes 500 to 3000 milliseconds anyway.

Without reranking, hybrid search alone is still a significant improvement over dense-only retrieval. If latency constraints prevent adding a reranker, hybrid search without reranking is better than dense-only with reranking in most evaluations. The reranker adds precision, but the recall improvement from hybrid search is more fundamental because you cannot rerank a document into the top results if it was never retrieved in the first place.

Common Implementation Mistakes

The most common mistake is using different tokenization for ingestion and query-time BM25. If your ingestion pipeline tokenizes with one method and your query pipeline uses another, the term statistics will not match and BM25 will underperform. Use the same tokenizer, stemmer, and stop-word list for both.

The second mistake is not stripping metadata from chunks before BM25 indexing. If your chunk text includes source markers, section headers, or other metadata, BM25 will match on those metadata terms rather than the content. Index only the natural language content for BM25, not the metadata.

The third mistake is setting k too low in the retrieval step when using hybrid search. Because hybrid search merges two lists, the top-k from each list may have significant overlap, meaning the union of results is smaller than 2k. Retrieve at least 20 candidates from each method to ensure adequate coverage after merging.

The fourth mistake is not evaluating hybrid against dense-only on your specific data. While hybrid search wins on average across benchmarks, there are narrow domains (highly technical corpora with consistent vocabulary, or conversational data where BM25 adds noise) where dense-only performs equally well. Always measure on your data before committing to the added complexity.

Key Takeaway

Hybrid search merges vector similarity with keyword matching using Reciprocal Rank Fusion, covering the failure modes of each individual method. Dense retrieval handles semantic meaning, sparse retrieval handles exact terms, and the combination consistently outperforms either alone by 5% to 15% on standard retrieval benchmarks. Most vector databases now support hybrid search natively, making implementation straightforward.