Most production search and RAG systems already run in one or two stages. Vector search maps a query and every document into the same embedding space and finds nearest neighbors, which is why it finds paraphrases that keyword search misses, as covered in the Elastic overview of vector search and the Weaviate explainer. The catch is that a bi-encoder compresses a whole chunk into one vector, so fine detail such as negation or an exact identifier can wash out, as Weaviate's chunking guide explains for chunk-level embeddings.
Hybrid retrieval adds a lexical scorer like BM25 and fuses the two ranked lists, usually with reciprocal rank fusion, which is a rank-only formula that avoids the score-scale mismatch between unbounded BM25 scores and bounded cosine similarity, per OpenSearch's RRF writeup and MongoDB's guide. Fusion improves recall, but it also mixes in more noise, which is exactly the condition where a second-stage scorer helps, as the Digital Applied hybrid search reference argues.
So the pipeline becomes three steps with three different jobs:
- Recall. Cast a wide net. Fetch 50 to 100 candidates from vector search, BM25, or both.
- Precision. Run a cross-encoder over those candidates and keep the top 5 to 10.
- Generate or display. Pass the shortlist to the LLM or the results page.
The important design rule is that reranking never rescues a document the first stage failed to return. If recall at 100 is 0.85, the reranker can only reorder that 85 percent. Teams that tune the reranker while their first stage misses relevant chunks are optimizing the wrong layer.



