Keyword search is best when you know the exact identifier, error string or config key. Vector search is best when you know what the code does but not what it is called. Code search benefits from both, with the two ranked lists merged into one.
What keyword search does well
BM25 is the standard ranking function for keyword search. It scores documents on how often query terms appear, adjusted for document length and how rare each term is. SQLite's FTS5 module includes a built in bm25 function, with better matches returning numerically smaller values, and supports phrase queries and prefix queries.
Keyword search is predictable. If you search ERR_CERT_EXPIRED, you get files containing it. You can explain every result.
What vector search does well
It handles vocabulary mismatch. A developer asks "how do we throttle requests per user" and the code says RateLimiter. Embeddings place those near each other. Our primer on embeddings explains why.
Where each fails
- Exact function name: keyword search is strong, vector search is can miss.
- Error code or CVE id: keyword search is strong, vector search is weak.
- Described behaviour: keyword search is weak, vector search is strong.
- Typos in the query: keyword search is weak, vector search is better.
- Explaining a result: keyword search is easy, vector search is hard.
Anthropic's retrieval article makes the same point: embeddings capture meaning but can miss exact matches, and BM25's lexical matching helps with identifiers and technical terms. They report that embeddings plus BM25 outperform embeddings alone.
How hybrid retrieval merges results
Run both searches. You now have two ranked lists with scores on different scales, so you cannot add the scores directly. A common fix is rank fusion: score each document by its position in each list, then sum. A document that appears near the top of both lists wins. Duplicates are merged.
A typical pipeline:
- Take the top 50 or so from keyword search.
- Take the top 50 or so from vector search.
- Fuse by rank and deduplicate.
- Optionally rerank the fused list with a stronger model, covered in reranking explained.
- Pass the top handful to the model.
Anthropic's pipeline retrieved about 150 candidates, reranked, and passed the top 20 to the model. Their reported failure rate fell from 5.7 percent for plain embeddings to 1.9 percent for the full pipeline. Again, their data, so run your own test.
Start with keywords
If you are building from scratch, start with keyword search over a local database. It is cheap, fast and gives you a baseline. Then add vectors and measure whether recall improves on your own questions. A short FTS5 how to shows the first step.
Quick check
Is vector search a replacement for grep?
No. Grep and keyword indexes answer a different question. Keep both available.
Do I need a vector database for hybrid search?
Not at small scale. A relational database with a vector extension, or even an in memory index, can do it. See vector database or not.
Sources
Last reviewed: 19 October 2026.