Skip to main content
search

Search Engine (Elasticsearch, OpenSearch, Meilisearch)

Inverted-index-based full-text and structured search — the right tool for 'find me records matching this query' when SQL LIKE isn't fast enough.

Why it exists

SQL LIKE '%foo%' is O(N) — a full table scan. At any real scale, full-text search on a relational database is unusable. Search engines flip the model: they build an inverted index (word → list of document IDs containing it) so queries are O(matches), not O(rows). They also handle relevance scoring, faceted filtering, fuzzy matching, and aggregation in a way that's painful in SQL.

How it works

At index time, each document is analyzed: tokenized into terms, lowercased, stemmed, and possibly filtered (stopwords). Each term is added to the inverted index pointing to the doc ID. At query time, the search engine tokenizes the query the same way, retrieves candidate docs from the index, scores them (BM25 by default), and returns the top-K. Sharding splits the index across nodes; queries fan out and results are merged. Elasticsearch uses Lucene under the hood.

Scaling characteristics

A single Elasticsearch node handles ~10K QPS for typical queries; complex aggregations are 10-100× slower. Sharding scales writes and index size linearly. Replication provides read scale + fault tolerance. Index size dominates memory: keep the working set in RAM for fast queries. Rule of thumb: 20-30 GB per shard, ~1 shard per CPU core.

When to use it

  • Full-text search over documents, articles, or products
  • Faceted search + filters (e-commerce: brand, price range, in-stock)
  • Log aggregation and search (Elasticsearch + Kibana = ELK stack)
  • Autocomplete and suggestion
  • Ad-hoc analytics on structured data with high cardinality
  • Geo-spatial queries (find restaurants within 2 miles)

When NOT to use it

  • Transactional storage — search engines aren't ACID; treat them as a derived index
  • Small datasets where SQL indexes work fine
  • Queries requiring cross-document JOINs — search engines are single-index by design
  • Very high write rates without careful sharding

Failure modes

  • Split-brain during network partition (Elasticsearch quorum matters) — set minimum_master_nodes carefully
  • Index corruption during power loss without proper flush settings — always enable translog fsync
  • Query overload from complex aggregations — set search timeouts + circuit breakers
  • Reindexing during schema changes takes hours to days — plan capacity and use aliases for zero-downtime cutover
  • Cluster overload from too many small shards — every shard has overhead; keep them large

Alternatives

  • PostgreSQL full-text search (pg_search, tsvector) — good enough for <10M docs; keeps you on one datastore
  • Meilisearch / Typesense — simpler, developer-friendly, great for typo-tolerance out of the box
  • Algolia — hosted, best-in-class relevance out of the box, expensive at scale
  • Vector search (pgvector, Pinecone, Qdrant) — for semantic search, replaces or complements keyword search

Interview questions

  • Explain the difference between an inverted index and a B-tree. When would you prefer which?
  • How do you handle a schema change on a 1TB Elasticsearch index?
  • What are the trade-offs of using Elasticsearch as your source of truth vs an index derived from Postgres?
  • How would you build autocomplete for 100M product names with typo tolerance?
  • Your Elasticsearch cluster is running out of heap. What's your diagnostic sequence?
  • How does BM25 scoring differ from TF-IDF, and when does it matter?
The story of full-text search

1990, Cornell: the inverted index changes how computers find text

In the late 1980s, if you wanted to search text, you scanned files linearly. Grep worked. Real search didn't. Then Gerard Salton at Cornell — a librarian's son who'd spent 30 years on the SMART system — codified the algorithms that made real search possible: the inverted index, TF-IDF scoring, and cosine similarity. His 1988 book Automatic Text Processing is still cited today. When Salton died in 1995, Sergey Brin was reading his papers in a Stanford library.

The industrialization came in stages. Apache Lucene (1999, Doug Cutting) turned Salton's algorithms into production-grade Java. Apache Solr (2004, Yonik Seeley) wrapped Lucene in a REST API. Elasticsearch (2010, Shay Banon) added distributed operation and JSON. OpenSearch forked from Elasticsearch in 2021 after license disputes. Meanwhile, Google went in a different direction — proprietary systems with PageRank + neural signals. Modern search stacks combine lexical (Lucene-family) and semantic (vector embeddings) approaches.

2023 changed everything. LLMs made vector search mainstream. Every major search engine added HNSW indexes for approximate nearest neighbor. Pinecone, Weaviate, Qdrant emerged as pure vector DBs. Retrieval-Augmented Generation (RAG) became the dominant AI pattern — and RAG is just "semantic search + LLM." Suddenly search is at the center of every modern AI product.

The core insight: search is not "LIKE '%foo%'". It's a ranked retrieval system — you don't want "matches yes/no," you want "which 10 documents best match this query, ranked by relevance?" Lexical search answers "does the query appear?". Semantic search answers "is this document about the query?". Modern search does both, then blends the results with rerankers to give you the best of each.

Search stack layers
1. Analyzer
Tokenize → lowercase → stem → filter. "Runs" → "run".
2. Inverted index
term → posting list of doc IDs. The core data structure.
3. Scoring
BM25 for lexical, cosine for vector. Rank documents by relevance.
4. Distributed shards
Fan-out to shards, aggregate top-K globally.
Modern reality: production search fuses lexical BM25 + semantic vector search + LLM rerankers. The final result is "hybrid."

Historical timeline

  1. 1960s
    SMART project at Cornell
    Gerard Salton starts building the algorithms of information retrieval. Foundation for all future search.
  2. 1975
    Vector space model formalized
    Salton et al. publish "A Vector Space Model for Automatic Indexing." Documents as vectors, queries as vectors, cosine similarity as ranking.
  3. 1988
    TF-IDF codified
    Salton's Automatic Text Processing book crystallizes term-frequency-inverse-document-frequency scoring.
  4. 1994
    Okapi BM25 published
    Stephen Robertson at City University London formalizes BM25 — a probabilistic improvement over TF-IDF. Still the industry default lexical scorer.
  5. 1998
    Google + PageRank
    Sergey Brin + Larry Page publish PageRank at Stanford. Link-based ranking. Transforms web search.
  6. 1999
    Apache Lucene 1.0
    Doug Cutting releases Lucene — Java library implementing Salton's algorithms production-grade. Powers most non-Google search for the next 20 years.
  7. 2004
    Apache Solr
    Yonik Seeley builds a REST/HTTP wrapper around Lucene. Makes Lucene approachable for web developers.
  8. 2010
    Elasticsearch 1.0
    Shay Banon releases Elasticsearch — distributed, JSON-native Lucene. Explodes in popularity. Becomes THE search stack of the 2010s.
  9. 2013
    Word2Vec
    Mikolov et al. at Google publish Word2Vec. Words as dense vectors. Foundation for modern semantic search.
  10. 2018
    BERT + neural rerankers
    Google's BERT model shows transformers understand context better than any prior model. Search engines integrate BERT for reranking.
  11. 2019
    HNSW paper matures
    Malkov & Yashunin's Hierarchical Navigable Small Worlds becomes the standard ANN index. Powers Pinecone, Weaviate, Milvus.
  12. 2021
    OpenSearch forks from ES
    AWS + Elastic license dispute → OpenSearch fork. Enterprise splits between the two. Open-source vs SaaS narrative.
  13. 2022
    Pinecone + Weaviate + Qdrant GA
    Purpose-built vector DBs achieve production maturity. Emerging category.
  14. 2023
    RAG becomes the AI paradigm
    GPT-4 + vector search = every AI app. Search is at the center of AI infrastructure.
  15. 2024
    Hybrid search dominates
    BM25 + vector fusion (reciprocal rank fusion). LLM rerankers. Elastic, OpenSearch, Vespa all ship first-class hybrid.

The inverted index — foundation of full-text search

An inverted index flips the data model on its head. Instead of "doc → words," it's word → docs. Look up any term → get the list of docs containing it. O(1) per term. Try searching:

Documents indexed
doc 1: The quick brown fox jumps over the lazy dog
doc 2: A quick blue fox runs through the forest
doc 3: The lazy dog sleeps by the fire
doc 4: Foxes and dogs are common in fairy tales
Query tokens → posting lists
fox → [ 1, 2 ]
Result set (AND intersect)
Docs: [ 1, 2 ]
Why this is fast: to find "lazy dog," look up "lazy" (docs 1, 3), "dog" (docs 1, 3, 4), intersect → [1, 3]. Two hash lookups + one merge. O(sum of posting-list sizes), not O(all documents). At 1B docs, still ms.

Analyzer pipeline: from raw text to searchable tokens

Before text hits the index, it goes through an analyzer: tokenize → normalize → stem → filter. Same pipeline runs on both indexed docs and queries — so "Running" matches "runs." Type in text and watch each stage:

1. Tokenize (whitespace split)
[ "The", "Running", "Foxes", "are", "jumping", "quickly!" ]
2. Strip punctuation
[ "The", "Running", "Foxes", "are", "jumping", "quickly" ]
3. Lowercase
[ "the", "running", "foxes", "are", "jumping", "quickly" ]
4. Remove stopwords (the, and, is, ...)
[ "running", "foxes", "jumping", "quickly" ]
5. Stem (running → run, foxes → fox)
[ "runn", "fox", "jump", "quick" ]
Analyzer symmetry: the same pipeline runs on the query. So "runs" user typed → stemmed to "run" → matches docs where "running" was also stemmed to "run." Change the analyzer & you must reindex.

Scoring: BM25, the industry default

"Matches" isn't enough — you need to rank. Lexical search uses BM25 (Best Match 25), a probabilistic model that scores each doc by:

score(D, Q) = Σ IDF(q_i) · (f(q_i, D) · (k1 + 1))
                        ─────────────────────────────
                        f(q_i, D) + k1·(1 - b + b·|D|/avgdl)
IDF (inverse doc frequency)
Rare terms score more. "quantum" is more informative than "the."
f(q_i, D)
Term frequency in doc. More occurrences = higher score, but with diminishing returns.
|D| / avgdl
Length normalization. A 5-word doc mentioning "fox" is more "about" foxes than a 500-word doc mentioning it once.
k1 (~1.2), b (~0.75)
Tunable knobs. k1 controls term-frequency saturation. b controls length normalization.
BM25 vs TF-IDF: BM25 (1994) improves on TF-IDF (1970s) by saturating term-frequency contribution (diminishing returns) and normalizing for doc length. Almost always better.
The scores are relative: BM25 scores aren't probabilities. They're only meaningful within a single query's result set. Don't compare scores across queries.

Vector search: understanding meaning, not just keywords

Lexical search finds documents that share words with the query. Vector search finds documents that share meaning. The trick: represent each document as a high-dimensional vector (typically 384-1536 dims) computed by an embedding model. Similar meanings → nearby vectors → cosine similarity ranks them.

Lexical (BM25)

Query: "cheap flights to Paris" → matches docs containing exact words.

✓ "Book cheap flights to Paris now!"
✗ "Budget airfare France" (different words!)

Precise but literal. Misses synonyms and paraphrases.

Semantic (vector)

Query embedding is a 768-dim vector. Compared to doc embeddings via cosine.

✓ "Book cheap flights to Paris now!" (obvious)
✓ "Budget airfare France" (similar MEANING)

Understands paraphrasing. Great for RAG + Q&A.

HNSW: how vector search stays fast at scale

Comparing your query vector against 100M doc vectors linearly = too slow. HNSW (Hierarchical Navigable Small Worlds) is the industry-standard approximate nearest-neighbor index. Builds a multi-layer graph where top layers are sparse (long jumps) and bottom is dense (fine-grained). Search starts at the top, greedy-descends. O(log n) instead of O(n).

Recall vs speed: HNSW has tuning knobs (M, efConstruction). Typical: 95-99% recall at 10-100x faster.
Memory: HNSW needs to hold graph in RAM. Modern deployments quantize vectors (16-bit or 8-bit) to fit more.
Alternative: IVF (inverted file) partitions into clusters. Faster to build, slightly worse recall. Faiss default.
Hybrid is the winner: combine BM25 + vector via reciprocal rank fusion. Get lexical precision + semantic recall. Standard in Elastic 8+, OpenSearch, Vespa, Weaviate. This is what production RAG stacks actually do.

Scaling: shards for capacity, replicas for throughput

A single Lucene index maxes out around 100M-1B docs. Beyond that: shard — split the index across nodes. Add replicas to serve more queries in parallel. Elasticsearch/OpenSearch default: 1 primary + 1 replica.

Shard 1 (primary + 2 replicas)
Doc IDs 0-999,999. Node A (primary), Node B (replica), Node C (replica).
Shard 2 (primary + 2 replicas)
Doc IDs 1M-1.999M. Node B (primary), Node C (replica), Node A (replica).
Shard 3 (primary + 2 replicas)
Doc IDs 2M-2.999M. Node C (primary), Node A (replica), Node B (replica).
Query lifecycle: client sends query → coordinator picks one replica of each shard → fans out → each shard returns top-K → coordinator merges + returns top-K globally. This is called "scatter-gather."
Shard count: pick at index creation. Can't easily change. Rule of thumb: 20-50GB per shard, up to 200GB.
Replica count: tune anytime. More replicas = more read QPS + more storage cost.
Cross-shard scoring caveat: BM25 scores are computed per-shard. If shards have very different corpora, ranking can drift. Use dfs_query_then_fetch for correctness.

Product comparison

ProductTypeModelStrengthWeakness
ElasticsearchGeneralOSS (SSPL) + ManagedMassive ecosystem. Best-known. Rich query DSL. Kibana visualization.Elastic License change (2021). JVM ops. Cost at scale.
OpenSearchGeneralOSS (Apache 2.0) + AWS ManagedFree of Elastic license constraints. AWS-backed. Feature parity with ES7.Community catch-up post-fork. Some diff from Elastic latest features.
Apache SolrGeneral (older gen)OSSMature. Battle-tested at large orgs (Bloomberg, Netflix legacy). Robust config.UX less modern than ES. Community activity lower.
VespaGeneral + ML-nativeOSS + CloudServes at Yahoo scale. First-class vector search + tensor ranking. Real-time indexing.Steeper learning curve. Smaller community than ES.
MeilisearchGeneralOSS + CloudInstant search UX out of the box. Fast, simple. Great DX.Not for petabyte scale. Fewer features than ES.
TypesenseGeneralOSS + CloudSub-50ms P99 search. Simple ops. Alternative to Algolia.Younger. Fewer integrations.
AlgoliaGeneral (managed)Managed onlyBest-in-class DX. Sub-50ms globally. Great for e-commerce site search.Expensive at scale. Vendor lock-in.
PineconeVector DBManagedFirst mover in managed vector search. Simple API. Great for RAG.Only vectors. Expensive. Multi-tenant, some scaling limits.
WeaviateVector + hybridOSS + CloudOSS. Hybrid search built in. GraphQL API. Rich modules for embedding.Younger. Complex configuration.
QdrantVector DBOSS + CloudRust performance. Payload filtering rich. Free tier generous.Smaller ecosystem than Pinecone.
MilvusVector DBOSS + Zilliz cloudScales to billions of vectors. Industrial-grade. Kubernetes-native.Operational complexity for self-hosted.
pgvector (Postgres extension)Vector in SQL DBOSSVector search inside your Postgres. Free. Zero new infra. HNSW support (0.5+).Not as fast as pure vector DBs at billion-scale. Single-node ceiling.

How to choose: Enterprise general search → Elasticsearch or OpenSearch. Site search managed → Algolia or Typesense. Vector-heavy RAG → Pinecone (managed) or Qdrant (OSS). Small budget or already on Postgres → pgvector. Yahoo-scale + ML ranking → Vespa.

12 real-world search deployments

GitHub

Elasticsearch for code search

GitHub's repo + code search runs on a custom Elasticsearch fork. Millions of repos indexed. Tokenizes code smartly (respects camelCase, snake_case). Recently replaced with Blackbird for scale — but ES powered them for a decade.

Uber

Elasticsearch for driver search

Uber uses ES to find nearby drivers in real-time via geo queries + ES aggregations. Handles million-QPS at peak. Multi-region deployment for locality.

Wikipedia

CirrusSearch on Elasticsearch

Wikipedia's search backend, CirrusSearch, is Elasticsearch. Indexes ~60M articles. Serves 100M+ searches/day. Custom scoring for wiki-specific relevance (redirects, categories).

Netflix

Elasticsearch → in-house TimeSeries + logs

Netflix used ES for logs, metrics, security events at massive scale. Recently split some workloads to in-house tools. The famous "Mantis" project used ES for real-time event debugging.

Shopify

Elastic + LLMs for product search

Shopify runs their storefront product search on Elasticsearch. Recently added semantic search via OpenAI embeddings. Millions of merchant storefronts, billions of products.

OpenAI ChatGPT

Vector search for RAG in Enterprise

ChatGPT Enterprise's document search uses vector embeddings + retrieval before feeding relevant chunks to GPT-4. This is RAG. Every enterprise AI product does this now.

Notion

Meilisearch → OpenSearch migration

Notion's search grew from Meilisearch to OpenSearch. Full-text + document titles + fuzzy matching. Query-suggestion powered by learned models.

Perplexity AI

Custom search + LLM synthesis

Perplexity does web search + LLM answering — retrieval-augmented generation at product scale. Their "search engine" is a hybrid of Bing web + LLM reranking + citation generation.

Stack Overflow

Elasticsearch for the world&apos;s Q&amp;A

Stack Overflow indexes ~20M questions in Elasticsearch. Custom scoring that weights answers-with-accepted-answer higher. Handles >100M searches/mo.

Etsy

Solr + custom ranking for e-commerce

Etsy uses Apache Solr for product search on 100M+ listings. Custom ranking uses TF-IDF + machine-learned CTR features. Personalized results per user.

Airbnb

Custom search built on OpenSearch

Airbnb's listing search runs on OpenSearch with heavy custom ranking. Location, availability, price, amenities all weighted. Millions of geographic queries daily.

Bloomberg Terminal

Legacy Solr for financial news

Bloomberg Terminal's document search runs on Apache Solr. Regulatory filings, news, research reports — millions of docs, sub-100ms search. Old but rock-solid.

Key takeaways

  • 1Search is ranked retrieval, not filtered SELECT. Get 10 best-matching docs, ranked by relevance.
  • 2The inverted index (term → posting list of doc IDs) is the core data structure. O(1) per term.
  • 3The analyzer pipeline (tokenize → lowercase → stem → filter) must run identically on docs and queries. Change it = reindex.
  • 4BM25 is the industry-default lexical scorer. Beats TF-IDF. Tunable via k1 and b.
  • 5Vector search (HNSW + cosine similarity) finds documents by meaning. Standard for RAG.
  • 6Hybrid search (BM25 + vector, fused) beats either alone. Production RAG uses this.
  • 7Scale via shards + replicas. Shards for capacity, replicas for query throughput.
  • 8For most workloads: Elasticsearch or OpenSearch for general. Pinecone/Qdrant/Weaviate for pure vector. Algolia for managed site search. pgvector when you're already on Postgres.

References & further reading

  • Salton, G. et al. (1975). "A Vector Space Model for Automatic Indexing." CACM. Foundation of modern search.
  • Salton, G. (1988). Automatic Text Processing. Addison-Wesley. The bible.
  • Robertson, S. et al. (1994). "Okapi at TREC-3." The BM25 paper.
  • Manning, C., Raghavan, P., Schutze, H. (2008). Introduction to Information Retrieval. Cambridge. Free online. The modern textbook.
  • Malkov, Yu. A. & Yashunin, D. A. (2018). "Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs." The HNSW paper.
  • Devlin, J. et al. (2018). "BERT: Pre-training of Deep Bidirectional Transformers." The paper that made neural rerankers mainstream.
  • Elasticsearch Docs: "A Practical Introduction to the Vector Space Model" blog + "Query DSL" reference.
  • Lucene JavaDoc: Actually reading the source is faster than reading blogs about it.
  • Doug Turnbull, John Berryman (2016). Relevant Search. Manning. Excellent practical scoring guide.
  • Vespa Documentation: The best hybrid + ML-ranking reference in the OSS world.
  • Pinecone Learning Center: Best vector-search-for-devs content anywhere.