System Design · Note 22 of 22
Design Search Autocomplete (Typeahead)
Quick answer
How do you design a search autocomplete system?
Store popular queries in a trie and keep, at every prefix node, the top few queries below it ranked by frequency. A keystroke walks one node down and returns that stored list. An offline pipeline aggregates query logs, rebuilds the trie periodically and swaps it onto replicated, cached servers, sharded by prefix when it outgrows one machine.
On this page
Autocomplete suggests whole queries while the user types. It is read-heavy, latency-critical (every keystroke) and tolerant of slightly stale results.
Requirements
- Functional: given a prefix, return the top 5–10 queries; ranked by popularity.
- Non-functional: fast enough to keep up with typing, so the latency target is agreed up front; highly available; suggestions may lag new trends a little.
- Scale: one request per keystroke, so several requests per search — estimate it with back-of-the-envelope numbers.
The trie
- One node per character; queries sharing a prefix share its path.
- A node that ends a query keeps its count (how often it was searched).
Insert "to" (searched 50 times): one node per letter, and the last node marks a complete query with its count.
Transcript · 7 steps
Top k at every node
- Each node stores its top k queries below it.
- Built bottom-up: a node merges its own query with its children's lists.
- Costs memory; buys a lookup with no subtree scan.
Each node stores its top 3 queries so a lookup never scans a subtree. "tre" has one query below it: tree 40.
Transcript · 4 steps
Serving a keystroke
- Walk one node per typed character, return the stored list.
- Cost grows with the prefix length, not with how many queries it matches.
- Debounce in the client, and cache short prefixes — they are the hottest.
The user types "t". The service steps one node down from the root and returns the list stored there: to, tree, try.
Transcript · 4 steps
Data collection and rebuild
- Every search is logged, off the serving path.
- An aggregator counts queries per window; old windows may weigh less.
- A builder makes a new trie periodically; replicas swap to it one at a time.
- The serving trie is read-only: no locks on the hot path.
Every search is logged. While the serving trie (v1) still offers tree 40, try 36, trie 25 for "tr", new queries pile up in the logs.
Transcript · 5 steps
Scaling it
- Replicas of the trie for read throughput; a load balancer in front.
- Caching: browser and CDN for popular prefixes, a cache beside the service.
- Sharding by prefix: ranges like
a–ap,aq–c, sized by traffic, not by letter. - Filtering: a blocklist for unsafe queries, applied before results leave.
- Personal or trending results: blended from a smaller, faster path.
Interview questions
- Why a trie and not a database LIKE query? A
LIKE 'pre%'query ranks matches on every request; a trie with stored top k answers in a walk and a read. - How do you rank suggestions? By search frequency over a recent window, then adjusted by freshness, personalisation and filters.
- How do new trends appear? At the next rebuild; for faster trends, a short-window counter blended into the results.
- How do you shard? By prefix range, with busy prefixes split further so each shard has similar traffic.
Next: back to System Design · Before this: Design a Web Crawler
Common questions
What data structure is used for autocomplete?
A trie (prefix tree): each node is one character, so every query sharing a prefix shares the path to it. Storing the top suggestions at each node turns a lookup into a walk of the prefix's length plus one read.
Why store the top-k suggestions at every trie node?
Without them, a short prefix like "t" would need a scan of its whole subtree on every keystroke. Precomputing the lists offline costs memory but makes each lookup fast and predictable.
How are autocomplete suggestions ranked?
Commonly by how often the query was searched over a recent window, often weighted towards recent days. Real systems add signals such as personal history, location and freshness, and filter out unsafe or unwanted queries.
How often is the autocomplete trie updated?
It is usually rebuilt periodically from aggregated logs — hourly, daily or weekly depending on how fresh suggestions must be — rather than updated on every search. Trending topics can be handled by a smaller, faster path.
How do you scale an autocomplete service?
Replicate the trie for read throughput, cache responses for popular prefixes at the edge or in the browser, and shard by prefix when the trie no longer fits one machine, splitting busy prefixes further so shards carry similar load.