InterviewKata
System design · Worked design D26 of 46 · Social and content · Long form

Design a web search engine

Someone types three words, and within a few hundred milliseconds sees the ten best pages out of billions, with a sensible snippet for each. The crawler that fetches pages is Design D09 and the suggestions while typing are D10; this design is the part in between: building the index, answering queries across thousands of machines, and ranking well.

1. The prompt

"Design web search: given a query, return the most relevant pages from a crawl of the web, fast, with fresh results when news breaks."

What makes it hard:

2. Frame the problem

How many pages do we search?

About 10 billion indexed pages, from a much larger crawl.

Billions of documents means sharding the index across thousands of machines; this single number drives the architecture.

How many queries?

Around 100,000 queries a second at peak.

Every query fans out to every shard unless we're clever, so shard replicas and caching become essential.

How fast?

Results within 300 ms at p99.

With a fan-out to thousands of shards, each shard must answer far faster than that, and the slowest shards must not hold everyone up.

How fresh?

Breaking news within minutes; popular pages within a day; the long tail within weeks.

Different freshness for different content suggests two indexes: a big batch-built one and a small real-time one.

Is crawling part of this?

No, assume a crawler (Design D09) delivers fetched pages.

It keeps the scope on indexing, serving and ranking.

Personalised results? Ads? Images?

Light personalisation (language, country). No ads or image search for now.

Personalisation by locale is cheap; per-user ranking is a much bigger system.

Spelling correction and suggestions?

Correct obvious typos; suggestions are D10.

A small query-understanding step before retrieval.

How is "good" measured?

Human-rated relevance on sample queries, plus click behaviour.

Ranking changes need offline evaluation and A/B tests, which shape the deploy process.

3. What it must do

  1. A user can search with a text query and get the ten most relevant pages, with a title and snippet each, and more pages on request.
  2. The system can index new and changed pages from the crawler, with freshness depending on the kind of page.
  3. The system can remove a page from results quickly (legal requests, malware, the page is gone).

Not now: crawling (D09), suggestions while typing (D10), ads, image and video search, per-user ranking.

4. How well it must do it

TargetWhy this number
Latency: p99 under 300 ms end to end speedSearch is used dozens of times a day; slow results feel broken.
Relevance: ranking quality measured offline and online, never worse after a change data qualityRelevance is the product; every change is a risk to it.
Freshness: news searchable within 10 minutes, popular pages within a day load shapeBreaking-news queries are exactly when people search most.
Availability: 99.99%, degrading gracefully (partial results beat none) surviving failuresWith thousands of machines, some are always down.
Removals: a removed page disappears from results within minutes rules and complianceLegal takedowns and malware can't wait for the next index build.

5. Numbers that change the design

QuantityWorking→ so we…
Text to index10 B pages × ~20 KB of text ≈ 200 TB; the compressed index is a sizeable fraction of thatFar beyond one machine → so we shard: ~10 M pages per shard ≈ 1,000 shards
Fan-out100 K queries/s × 1,000 shards100 M shard lookups a second if every query hits every shard → so we cache results, add a smaller top tier, and replicate shards
TailIf each shard is slow 1% of the time, a query touching 1,000 shards is almost always slow (Module 02)→ so we hedge requests and accept partial results
Query repetitionPopular queries repeat heavily; a large share of traffic is a small set of queries→ so a result cache in front absorbs a big share of load

Skip estimating snippet storage: documents live in a separate store and are fetched only for the final ten results.

6. The nouns

documents   doc_id, url, title, text_key (blob), lang, quality, indexed_at        (document store, sharded by doc_id)
postings    term → [(doc_id, term_freq, positions)]  sorted by doc_id, compressed  (inside each index shard)
doc_stats   doc_id → length, static_score                                       (per shard, for ranking)
blocklist   url_hash, reason, added_at                                          (small, replicated to every front end)

7. The contract

GET /v1/search?q=hiking+boots&lang=en&page_token=…
    → {results: [{url, title, snippet}], next_page_token, corrected_query?}

internal  Shard.Search(query_terms, k, deadline)  → [(doc_id, score)]   (gRPC, one call per shard)
          Docs.Snippets(doc_ids, query_terms)     → [{url, title, snippet}]
          Indexer consumes crawled pages from a queue; RealtimeIndexer consumes a stream of news pages

Data flow: crawled page → parse and clean → tokenise (lower-case, split, stem) → write postings into index segments → publish segments to shards → serve.

8. First working version

One machine: an indexer, an inverted index, a document store, and a query service.

8.1 Indexing a page

The page's text is split into terms; each term's posting list gains this document. Lists are kept sorted by document ID so they compress well and can be intersected quickly.

8.2 Answering a query

Look up each query term's posting list, intersect them (or union, scoring partial matches lower), score candidates with a text-relevance formula such as BM25 (rare terms count more; a term repeated in a short document counts more), keep the top 10, then fetch titles and snippets.

Parked for later10 B pages on one machine (9.1) · long posting lists are slow to scan (9.2) · text relevance alone ranks spam well (9.3) · rebuilding the index for every new page (9.4) · the fan-out's slowest shard (9.5) · takedowns (9.6).

9. Make it hold up

9.1 Splitting the index latency · availability

ApproachWhy
✗ BadOne giant index on the biggest machine200 TB of text won't fit, and one machine can't serve 100 K queries a second.
~ GoodPartition by term: each shard owns some words' posting listsA query touches only its terms' shards, but multi-word queries must join huge lists across machines, and common words make hot shards.
✓ GreatPartition by document (~1,000 shards, each a full index of its pages), with replicas per shard and a small top tier of the highest-quality pagesEach shard answers independently; most queries are satisfied by the top tier; replicas add throughput and survive failures.

This is Module 12's scatter-gather, at web scale: a root server sends the query to one replica of every shard, each returns its top results, and the root merges them.

9.2 Fast posting lists latency

9.3 Ranking in stages relevance

ApproachWhy
✗ BadText match alone (BM25)Easy to game with repeated keywords; ignores page quality and what users actually choose.
~ GoodText match combined with a static quality score (link authority, spam signals)Much better, cheap to compute per document; still blind to intent and freshness.
✓ GreatA cascade: cheap scoring retrieves ~1,000 candidates per query; a learned ranking model (click signals, freshness, quality, text features) re-ranks them; an expensive model (often a neural re-ranker) orders the final few dozenSpend compute only where it changes the answer. Every model change is checked offline against human relevance ratings, then A/B tested.

9.4 Fresh results without rebuilding everything freshness

9.5 Taming the fan-out's tail p99 under 300 ms

ApproachWhy
✗ BadWait for every shardWith 1,000 shards, one slow shard per query is nearly certain: every query is slow.
~ GoodReplicas, and a deadline per shardFewer slow responses, but a deadline alone means missing results.
✓ GreatResult cache for repeated queries, the top tier first, hedged requests (ask a second replica if the first is slow), and partial results when a few low-tier shards miss the deadlineKeeps p99 low with a small loss in completeness users rarely notice ("The Tail at Scale").

9.6 Removing a page fast removals within minutes

Rebuilding the index for one URL is far too slow. Keep a small blocklist replicated to every front end and filter results at serve time; the next index build drops the page permanently. The result cache is invalidated for affected queries, or simply filtered on the way out.

9.7 The whole design after the deep dives

10. Interviewer follow-ups

Ten times the queries.

Add replicas per shard (queries scale with replicas, not shards) and more front ends; the result cache absorbs repeated queries. The index size is unchanged, so no re-sharding is needed.

Ten times the pages.

More shards, and the fan-out grows, so lean harder on tiering: a top tier answers most queries, and deeper tiers are searched only when it doesn't return enough good results.

A whole shard's replicas are down.

Return results without that slice of the web; most queries won't notice, especially if it's a low tier. Alert, and rebuild the shard from the stored segments on new machines.

Spammers stuff pages with keywords.

Text match is only the first stage: quality scores, link signals, spam classifiers and user behaviour demote such pages. Spam detection runs in the indexing pipeline and feeds the static score.

Add semantic (meaning-based) search.

Add an embedding for each document and an approximate nearest-neighbour index (Module 29), retrieve candidates from both it and the keyword index, and let the ranking cascade combine them (hybrid search).

Personalise results.

Keep the index global; apply personal signals only in the re-ranking stage, using features like language, location and recent history, within the privacy rules.

A court orders a URL removed in one country.

The blocklist entry carries the countries; front ends filter by the user's country. Record the request for audit.

How do you ship a ranking change safely?

Offline: compare against human relevance ratings on thousands of queries. Online: an A/B test on a small share of traffic, watching clicks, reformulations and abandonment. Roll out gradually; keep the old model ready.

Make it cheaper.

More caching, a smaller top tier serving more queries, tighter compression, cheaper first-stage scoring, and running the expensive models on fewer candidates.

Searches spike when big news breaks.

The real-time index is small and replicated widely; the result cache catches the many identical queries; the ranking boosts freshness for queries detected as news.

11. When things break

FailureWhat users seeHow we detect itWhat limits the damage
Slow shard replicaNothing, ideallyPer-replica latencyHedged requests; eject slow replicas
Bad index segmentMissing or odd resultsSample-query checks before rollout; result-count anomaliesRoll segments replica by replica; keep the previous version
Ranking model regressionWorse resultsClick and abandonment metrics; offline evaluationGradual rollout; instant switch back
Real-time index lagStale newsAge of newest indexed documentAlert; the main index still serves
Result cache downSlower resultsCache hit rate; shard loadShards are sized to survive a cold cache briefly; shed deep tiers first
Document store slowResults without snippetsSnippet latencyReturn titles and URLs; fill snippets later

12. Wrap-up and the clock

Trade-offs we made:

What we'd watch: p99 latency · share of queries with partial results · cache hit rate · real-time index lag · relevance metrics from clicks and ratings · per-shard load.

At 10×: more replicas for queries, more shards and tiers for pages, more caching.

A 60-minute interview

0–5Frame: corpus, queries, latency, freshness
5–10Must do, how well, the index-size and fan-out numbers
10–15Nouns, contract, data flow
15–25First version: indexing and querying one machine
25–50Deep dives: sharding (9.1), ranking (9.3), the tail (9.5)
50–60Freshness or removals, follow-ups, wrap-up

A 90-minute interview

0–8Frame, including how relevance is measured
8–15Must do, how well, numbers
15–22Nouns, contract, data flow
22–35First working version
35–75Deep dives 9.1–9.6 and the final picture
75–85Follow-ups: semantic search, spam, shipping ranking changes
85–90Trade-offs, metrics, 10×
LevelWhat a strong answer shows
Mid-levelAn inverted index, sharding with scatter-gather, a result cache, BM25-style scoring, a batch indexing pipeline.
SeniorDocument vs term partitioning with reasons, the fan-out tail and its fixes, a ranking cascade, a real-time index next to the batch one, serve-time removals.
Staff+Tiering and cost per query, evaluation methodology for ranking (offline ratings plus A/B), safe segment and model rollouts, hybrid keyword and semantic retrieval, spam as an adversarial problem.

Common mistakes:

13. Try it, check yourself, read more

Inverted index playground. Eight tiny "web pages". Type a query and see each term's posting list, the candidate pages, and their BM25 scores. Notice how a rare word counts more than a common one, and how a short page that repeats your word ranks above a long one. The page called "Boots" is keyword stuffing: it scores near the top on text match alone, which is why real ranking adds quality signals (9.3).

    BM25 with k1 = 1.2 and b = 0.75; words are lower-cased and a few common endings are stripped. Real engines add positions (phrases), quality scores and learned re-ranking on top.

    How is a web-scale index usually partitioned?

    Document partitioning keeps shards independent; term partitioning makes multi-word queries join huge lists across machines.

    A query fans out to 1,000 shards. What keeps its p99 low?

    With that many shards one is almost always slow; don't let it set everyone's response time.

    How do news pages appear within minutes when the main index is rebuilt daily?

    Like an LSM tree: big immutable segments plus a small fresh one, searched together.

    A page must disappear from results today. What's the fast path?

    Filtering at serve time takes effect in minutes; the index catches up later.
    ResourceWhy
    The Anatomy of a Large-Scale Hypertextual Web Search Engine (Brin and Page, 1998)The original architecture: crawl, index, rank by links.
    Challenges in Building Large-Scale Information Retrieval Systems (Jeff Dean, WSDM 2009)How the serving system evolved: sharding, tiers, encoding, caching.
    The Tail at Scale (Dean and Barroso)Hedged requests and why fan-outs are slow.
    Introduction to Information Retrieval (Manning, Raghavan, Schütze)Inverted indexes, compression and scoring, free online.
    Okapi BM25 and learning to rankThe first-stage formula and the learned re-ranking stage.
    Near real-time search (Elastic docs)How new documents become searchable within a second in Lucene-based engines.