system-design · intermediate
Design Search Autocomplete — Typeahead Suggestions
Start here
Search autocomplete (typeahead) shows suggestions while the user types:
in → instagram, invoice template, india news
Requirements: very low latency, high QPS, results that feel relevant/popular, and eventual updates as trends change.
What you will learn
- Clarify personalization vs global popularity MVP.
- Model prefix → top-k queries.
- Use tries or prefix indexes.
- Cache hot prefixes at the edge/app.
- Build offline/online update pipelines.
- Rate-limit and abuse-protect.
Words you need before we begin
| Term | Plain English |
|---|---|
| Prefix | Leading characters of the query string. |
| Trie | Tree of characters for prefix search. |
| Top-k | Best k suggestions under a ranking. |
| Frequency | How often a query is searched. |
| Offline pipeline | Batch job rebuilding suggestion tables. |
| Online update | Incremental adjustments (optional). |
Requirements
Functional
- Given prefix, return ≤10 suggestions
- Case normalization, basic Unicode note
- Optional: user recent searches
Non-functional
- p95 latency tens of ms
- High read QPS
- Eventual freshness of rankings (minutes–hours OK)
High-level design
flowchart LR
Client --> API
API --> Cache[(Prefix cache)]
API --> Idx[Prefix index service]
Logs[Search logs] --> Batch[Aggregator]
Batch --> Idx
Step-by-step design
Step 1 — Normalize
Lowercase, trim, maybe remove punctuation—document rules.
Step 2 — Data model
prefix → [(query, score)… top 10] materialised for common prefixes, or trie nodes storing top-k.
Step 3 — Query path
- Normalize input
- Check cache
- Lookup prefix index
- Return list
Step 4 — Ranking
Score ≈ frequency with time decay; maybe personalization as second phase.
Step 5 — Building the index
Stream search logs → aggregate counts → rebuild top-k per prefix offline every N minutes → atomic swap.
Step 6 — Caching
Cache empty and hot prefixes; short TTL; CDN rarely for personalized results.
Step 7 — Shard
Shard trie/index by first character(s) or hash of prefix for scale.
Failure modes
| Mode | Impact | Mitigation |
|---|---|---|
Hot prefix a | Hotspot | Extra cache; shard |
| Spam queries | Polluted suggestions | Filters; trusted logs |
| Rebuild failure | Stale suggestions | Keep last good index |
| Too slow DB joins | Miss latency SLO | Precompute top-k |
| Abuse bots | Cost | Rate limits |
Trade-offs
| Choice | Benefit | Cost |
|---|---|---|
| Precomputed top-k | Fast reads | Storage; rebuild |
| Live compute | Fresher | Hard at QPS |
| Personalization | Better UX | Privacy + complexity |
| Global only | Simple | Less relevant |
Common mistakes
SELECT … LIKE 'pre%'on primary DB at typeahead QPS.- Perfect ML ranking first.
- No rate limits.
- Updating trie on every keystroke write path.
- Ignoring Unicode/normalization.
Check your understanding
- What is stored for a prefix in the fast path?
- Why offline aggregation?
- How to handle hot prefixes?
- Min prefix length trade-off?
- Why cache empty results carefully?
Practice
- Estimate QPS if 10M users type 5 chars avg.
- Design trie node content for top-10.
- Sketch batch pipeline from logs to index swap.
- Add “remove unsafe suggestions” control.
- Mock interview.
Deeper production notes
Privacy
Search logs are sensitive—retention and access controls matter.
Multilingual
Tokenization differs by language; start with simple prefix for MVP and note evolution.
Additional teaching scenarios
Scenario A — 10× peak
Which component saturates first? First mitigation?Scenario B — dependency down 30 minutes
What still works? What degrades?Scenario C — five-sentence wrap
Requirements, core mechanism, scale lever, failure mode, trade-off.Revision summary
- Typeahead is a prefix → top-k read path.
- Precompute + cache; update via pipelines.
- Protect with rate limits and spam filters.
- Shard and cache hot prefixes.
Glossary
| Term | Definition |
|---|---|
| Typeahead | Suggestions while typing. |
| Trie | Prefix tree structure. |
| Top-k | Highest ranked k results. |
Abbreviations and terminology
- QPS — Queries per second
- TTL — Time to live
- p95 — 95th percentile latency
What to learn next
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Interview and production field guide for this topic
Use this section as deliberate practice, not filler. Rewrite the worked example for a second domain you know well—fintech, education, logistics, or media. Keep the same skeleton: requirements, estimates, high-level diagram, request path, data model, scale lever, failure modes, and trade-offs. If you cannot fill every section without copying buzzwords, you do not yet own the design.
Numbers to force yourself to state
Always speak order-of-magnitude figures: peak QPS, storage growth per day, fan-out factor, connection counts, or queue depth. Wrong numbers that are explicit beat silent hand-waving. Correct the numbers when the interviewer or teammate challenges them; that is collaboration, not failure.
Failure minute
Set a timer for sixty seconds and list only failures: timeouts, duplicates, hot keys, dependency outages, bad deploys, and data corruption paths. For each, name detection and first mitigation. Designs that only describe the happy path are incomplete for production and weak in interviews.
Ownership and operability
Name the dashboard, the alert, the runbook section, and the team that pages. If any are blank, the system will train you during an incident. Prefer progressive delivery: canaries, flags, and rollback notes written before the change lands.
Consistency and retries
State whether the design assumes at-least-once delivery, whether handlers are idempotent, and where unique constraints live. Retries without idempotency are how double charges, double messages, and duplicate fan-out jobs appear. Timeouts without bounds are how thread pools die.
What good looks like in a review
A strong design review or interview answer clarifies scope, makes assumptions audible, draws a minimal path, deepens one or two bottlenecks, and closes with trade-offs and evolution. Use that bar on design-search-autocomplete round 0 every time you revisit it.
Interview and production field guide for this topic
Use this section as deliberate practice, not filler. Rewrite the worked example for a second domain you know well—fintech, education, logistics, or media. Keep the same skeleton: requirements, estimates, high-level diagram, request path, data model, scale lever, failure modes, and trade-offs. If you cannot fill every section without copying buzzwords, you do not yet own the design.
Numbers to force yourself to state
Always speak order-of-magnitude figures: peak QPS, storage growth per day, fan-out factor, connection counts, or queue depth. Wrong numbers that are explicit beat silent hand-waving. Correct the numbers when the interviewer or teammate challenges them; that is collaboration, not failure.
Failure minute
Set a timer for sixty seconds and list only failures: timeouts, duplicates, hot keys, dependency outages, bad deploys, and data corruption paths. For each, name detection and first mitigation. Designs that only describe the happy path are incomplete for production and weak in interviews.
Ownership and operability
Name the dashboard, the alert, the runbook section, and the team that pages. If any are blank, the system will train you during an incident. Prefer progressive delivery: canaries, flags, and rollback notes written before the change lands.
Consistency and retries
State whether the design assumes at-least-once delivery, whether handlers are idempotent, and where unique constraints live. Retries without idempotency are how double charges, double messages, and duplicate fan-out jobs appear. Timeouts without bounds are how thread pools die.
What good looks like in a review
A strong design review or interview answer clarifies scope, makes assumptions audible, draws a minimal path, deepens one or two bottlenecks, and closes with trade-offs and evolution. Use that bar on design-search-autocomplete round 1 every time you revisit it.
FAQ from first-time learners
Q: Elasticsearch for autocomplete?
A: Valid; still discuss prefix structures, edge n-grams, and caching—do not stop at product name.
Q: Personalization required?
A: Mention as phase 2 unless interviewer insists.
Track: Distributed Systems
Previous: Design Instagram — Photos, Feed, and Fan-Out
Next: Design Uber — Matching Riders and Drivers
By Shubham Jain