Vector search vs full-text — when to use which
Vector search is the hot new thing, but full-text search remains the right answer for many use cases. Where each shines, where they fail, and why hybrid almost always beats either alone.
Every team I've talked to in 2026 either built or is building search features. The default question: vector or full-text? The wrong answer is "vectors, obviously, it's the future." The right answer depends on the queries your users actually run.
Full-text search (BM25, Elasticsearch, Postgres tsvector)
Indexes documents by their terms. Queries return documents containing the query's words, ranked by term frequency and document relevance (BM25 algorithm).
Wins when:
- Users search by exact terms, codes, identifiers.
- Products have specific names users know.
- Documents are short and indexable terms are meaningful.
- Search is heavily filtered (category, date, status).
- Latency matters — full-text is fast.
Fails when:
- Users describe what they want in natural language without using document terms.
- Synonyms matter ("car" vs "vehicle").
- Conceptual similarity matters ("how to fix login issues" should find "troubleshooting authentication").
- Typos and variations need to be handled gracefully.
Vector search (embeddings, pgvector, Pinecone, Weaviate)
Indexes documents as embeddings — high-dimensional numerical representations of meaning. Queries also become embeddings; nearest-neighbor search returns semantically similar documents.
Wins when:
- Users describe what they want in natural language.
- Documents express the same concept with different vocabulary.
- Multilingual content where queries and docs may be in different languages.
- Semantic similarity matters more than exact word matches.
- Question-answering and conversational search.
Fails when:
- Users search by exact codes, IDs, SKUs.
- Acronyms and rare technical terms (embeddings flatten them).
- Negative queries ("not red", "excluding 2019").
- Tight latency budgets (vector search is slower than BM25).
Real example: e-commerce search
User types "comfortable sneakers for running."
- Full-text matches "comfortable" and "running" in product descriptions. Returns products with those exact words.
- Vector understands "comfortable" + "sneakers" + "running" as semantic intent. Returns running shoes even if descriptions say "cushioned" instead of "comfortable."
Now user types "Nike Air Max 90 size 42."
- Full-text finds the exact product by SKU or model name.
- Vector might return Nike Air Max 95, similar but wrong.
Hybrid almost always wins
For most production search, the answer is both:
- Run full-text search and vector search in parallel.
- Combine results using reciprocal rank fusion (RRF).
- Return top-k merged results.
Hybrid retrieval consistently beats either alone in evaluation benchmarks by 10-30%.
Implementation in Postgres
You can do both in Postgres without separate infrastructure:
-- Full-text index
CREATE INDEX docs_fts ON docs
USING gin(to_tsvector('english', content));
-- Vector index (with pgvector extension)
CREATE INDEX docs_vec ON docs
USING hnsw (embedding vector_cosine_ops);
-- Hybrid query
WITH ft AS (
SELECT id, ts_rank(to_tsvector('english', content),
plainto_tsquery('english', :query)) AS rank
FROM docs
WHERE to_tsvector('english', content) @@
plainto_tsquery('english', :query)
ORDER BY rank DESC LIMIT 50
),
vec AS (
SELECT id, 1 - (embedding <=> :query_embedding) AS rank
FROM docs
ORDER BY embedding <=> :query_embedding LIMIT 50
)
SELECT id, COALESCE(ft.rank, 0) + COALESCE(vec.rank, 0) AS score
FROM (SELECT * FROM ft UNION ALL SELECT * FROM vec) combined
GROUP BY id
ORDER BY score DESC LIMIT 10;
Real implementations use RRF or learned ranking instead of simple addition.
When to add re-ranking
After hybrid retrieval, a cross-encoder model re-ranks the top-20 results based on query-document relevance. Adds latency (50-200ms) but lifts precision significantly.
Worth it when search drives core product value and the top-3 results matter.
What to measure
- Recall@10 — is the relevant document in top-10?
- MRR (mean reciprocal rank) — at what position is the first relevant result?
- Click-through rate — do users click results?
- Latency p95 — search speed at 95th percentile.
Build an evaluation set of 100-500 queries with expected results. Measure regularly.
Verdict
Full-text for exact terms and identifiers. Vector for natural-language conceptual search. Hybrid for production because real users do both. Re-rank top-20 when precision matters. Don't pick one — combine.