AI Fundamentals

Hybrid Search Explained: Vector + Keyword Search with RRF

Semantic search misses exact identifiers; keyword search misses paraphrases. Hybrid search fuses both with reciprocal rank fusion — and it is the default your retrieval should start from.

February 17, 2026·7 min read

Hybrid search runs two retrieval methods on every query — dense vector (semantic) search and sparse keyword (full-text) search — and merges their results into one ranked list. It exists because each method fails in a way the other fixes, and documentation queries hit both failure modes daily.

The term sounds like an implementation detail, and in a sense it is: users never see "hybrid search" — they see that the right page came back, or did not. But for anyone building or buying a RAG system, it is the single most consequential retrieval decision, because everything downstream — reranking, answer generation, citations — can only work with what the first stage found. This essay explains what each method actually does, why fusion by rank beats fusion by score, and where hybrid search sits in a production pipeline.

What is vector search, and what does it miss?

Vector search embeds queries and passages into a shared semantic space — each becomes a list of numbers such that texts with similar meaning land near each other, measured by cosine similarity. This is what lets "rotate credentials" match a page titled "regenerate API keys": no shared words, near-identical meaning. It is also what makes retrieval work across languages and across the vocabulary gap between how users talk and how docs are written — the single biggest failure of classic site search.

But embeddings blur exact tokens. An embedding model compresses a passage into a fixed-size vector, and in that compression, error code E4022 lands almost exactly where E4021 does; getUserById sits beside getUserByEmail; --no-verify neighbors --no-validate. To the geometry these are siblings, and vector search will cheerfully return the wrong one. For a developer pasting an exact error code, "semantically similar but literally wrong" is worse than no result — it looks authoritative while answering a different question.

What is keyword search, and what does it miss?

Keyword search (BM25 or Postgres full-text ts_rank) is the mirror image. It matches on the actual tokens: a query containing E4022 finds the passages containing E4022, ranked by how rare and concentrated the matching terms are. Decades of search engineering have made this fast, cheap, and utterly reliable for exact identifiers — the error codes, function names, product names, and config flags that documentation queries are studded with.

Its blindness is the paraphrase. Keyword search has no concept of meaning, only of tokens: a user asking "why did my payment bounce?" never finds the page titled "failed transaction handling," because not one word overlaps. The user concludes the answer does not exist, and support gets a ticket for a documented issue. Docs queries are an even mix of both shapes — natural-language questions studded with exact identifiers, often in the same query: "why does getUserById throw E4022 when the user exists?" needs semantic matching for the intent and literal matching for the identifiers. Either method alone leaves recall on the floor.

Reciprocal rank fusion: merging by rank, not score

Running both searches produces two ranked lists — and a fusion problem, because the two methods produce incomparable scores. Cosine similarity lives roughly in [0, 1] with corpus-dependent meaning; BM25 scores are unbounded and shift with document statistics. Any weighted sum of raw scores is an apples-to-oranges calculation that breaks the moment your corpus changes.

Reciprocal rank fusion (RRF) sidesteps score normalization by combining ranks instead: each document scores Σ 1/(k + rank) across the result lists, with k ≈ 60. The intuition is simple. A document ranked highly by both methods accumulates two large contributions and rises to the top. A document only one method found still survives with one contribution — critical, because "only one method found it" is precisely the case hybrid search exists for. And the constant k damps the difference between rank 1 and rank 3 so that a slightly different ordering does not swing the fusion. Rank-based fusion is robust precisely because it ignores the raw scores: it needs no calibration, no per-corpus tuning, and no re-derivation when you swap embedding models.

Weighted RRF goes one step further, tilting the fusion toward the method that historically serves your corpus better — API references tend to reward the keyword side; conceptual guides reward the semantic side. It is a tuning knob worth having, but only once you can measure retrieval quality against a golden set of known questions and correct sources. Tuned by feel, weights are as likely to hurt as help; measured with recall@k against a baseline, they are a safe, incremental win.

Where hybrid sits in a full pipeline

In production RAG, hybrid search is the recall stage, not the whole story. Its job is to make sure the right passage is somewhere in the candidate list — cast the net wide, tolerate false positives, refuse false negatives. Precision comes later: a cross-encoder reranker reads the question and each candidate passage together — the only score in the pipeline computed from both at once — and puts the truly relevant passages at the top. Confidence thresholds then decide what the model actually sees, and whether the system should answer at all or abstain because nothing retrieved is good enough.

The ordering is load-bearing: a passage hybrid search misses can never be recovered downstream — no reranker can promote a candidate that is not in the list, and no language model can cite a passage it was never given. That is why the first stage is tuned for recall and everything after it for precision, and why hybrid — not pure vector search — is the correct default for the first stage. Every point of recall lost at stage one is subtracted from the ceiling of the entire system.

Do I really need hybrid? Common objections

"Modern embeddings are good enough on their own." They are remarkable, and they still compress. The identifier problem is not a quality gap that better training closes; it is inherent to representing text as fixed-size vectors. As long as your users paste error codes and function names — and in documentation, they always do — a literal index earns its keep.

"Can't the reranker fix a weak first stage?" No — a reranker reorders candidates; it cannot conjure them. If retrieval missed the passage, the reranker ranks the wrong candidates very precisely.

"Isn't this expensive to run?" Barely. With pgvector, the vector index and the full-text tsvector index live in the same Postgres row, both queries run in one round trip, and RRF is arithmetic. Hybrid search is one of the rare architecture choices that is simultaneously the more correct option and nearly free — most of the practical cost is upstream anyway, in chunking content well enough that both indexes have clean passages to find.

The takeaway

Retrieval failures are invisible by default: the user just sees a wrong or missing answer, and the model gets the blame. Hybrid search closes the two failure modes that account for most of them — the paraphrase keyword search cannot see and the exact identifier vector search cannot hold. Fused with RRF, the two methods cover each other's blind spots without fragile score calibration; measured against a golden set, the whole stage becomes tunable instead of mystical. If you are evaluating a RAG platform, ask specifically whether retrieval is hybrid, how results are fused, and what sits between retrieval and the model. If the answer is "we do vector search," you have found the ceiling of the product.

Turn your knowledge into answers

Connect your docs, policies, or playbooks and see cited AI answers in minutes — free, no credit card required.

Get Started Free