SkillPilotAI

Autocomplete / Typeahead

Showing top suggestions as soon as the user types 2-3 letters, within 100 ms on every keystroke.

21.1 Why is it used?

  • The user does not have to type everything, search is faster, and spelling mistakes are fewer.
  • Showing popular and trending queries first raises conversion (for example 'iphone 16' during a sale).
  • A request goes out on every keystroke, so traffic is many times the main search traffic - the system must be very fast and cheap.
  • Personalization: suggestions based on the user's past searches and location.

21.2 How it works

  • Trie (prefix tree): each node is a character, the path is the prefix; pre-store the top-K popular completions at each node so the lookup is O(prefix length).
  • Redis sorted sets (ZSET): one ZSET per prefix holding queries with a score (frequency); ZREVRANGE gives the top 10, ZINCRBY raises the count.
  • Redis ZRANGEBYLEX: all terms in a single sorted set at score 0, with a lexicographic range for prefix matching.
  • Elasticsearch completion suggester: fast prefix suggestions based on an in-memory FST; search_as_you_type / edge n-gram fields are also options.
  • Data pipeline: search logs to Kafka -> a batch/stream job counts each query's frequency -> trie/ZSET rebuild (every hour/day).
  • Client side optimizations: debounce (wait ~100-300 ms), send a request only after 2-3 characters, browser/CDN caching of popular prefixes.
  • Ranking: frequency + recency (trending) + personalization; filtering offensive/blocked terms is essential.
  • Fuzzy/typo tolerance: suggesting 'samsung' even for 'samsng' using edit distance.
A. Request flow: < 100 ms on every keystroke
  1. 1.User: types 'bir' (Swiggy app, 200 ms debounce)
  2. 2.CDN / edge cache: popular prefix cached city-wise; hit = instant answer
  3. 3.Suggest service: runs on a cache miss
  4. 4.Redis ZSET: ZREVRANGE suggest:blr:bir 0 9
  5. 5.Blocked words: filter offensive terms
  6. 6.Re-rank: the user ordered Hyderabadi biryani before, so it goes first
  7. 7.Suggestions ~30-50 ms: 1. hyderabadi biryani 2. biryani 3. birthday cake 4. biryani rice
B. Data structure: Trie (top-K at each node) vs Redis Sorted Set
  1. 1.Trie: root -> b -> bi -> bir
  2. 2.top-K @ 'bir': biryani, birthday cake, biryani rice
  3. 3.top-K @ 'bu': burger, butter naan
  4. 4.Redis ZSET key suggest:blr:bir: biryani 9820, birthday cake 4310, biryani rice 1250
  5. 5.ZINCRBY suggest:blr:bir 1 biryani: count +1
C. Popularity update pipeline (stream + nightly batch)
  1. 1.Search events: what the user searched
  2. 2.Kafka: search-logs topic
  3. 3.Flink job: counts every 5 min
  4. 4.ZINCRBY: updates Redis ZSETs
  5. 5.Nightly batch: trims to top-N

Mistake: calling on every keystroke without debounce -> 5-10x useless load on the backend. Mistake: LIKE 'bir%' on the main DB -> slow at scale; use a trie / ZSET / ES suggester

21.3 Tools you can use

ToolTypeHow it is used
Redis (Sorted Sets)In-memory data storePrefix -> ZSET of top queries with score; sub-ms reads, live popularity update with ZINCRBY.
Elasticsearch / OpenSearch Completion SuggesterSearch engine featurecompletion field type, fast prefix suggestions through an FST; with fuzzy and context (category) filters.
Custom in-memory Trie serviceSelf-built service (Java/Go)Top-K cached trie in memory, rebuilt by an offline job, sharded by prefix; at big scale like Google/LinkedIn.
AlgoliaSaaS searchQuery Suggestions and instant search out of the box, typo tolerance built in.
Kafka + Spark/FlinkData pipelineComputing query frequency from search logs to refresh the suggestion data.

21.4 Comparison: Trie vs Redis Sorted Sets vs Elasticsearch Completion Suggester

PointCustom TrieRedis Sorted SetsES Completion Suggester
SpeedFastest, in-process memorySub-ms, with a network hopFew ms, fast
Build effortHigh, own code + shardingMedium, simple commandsLow, mapping + data index
Live updatesHard, mostly periodic rebuildEasy, real-time with ZINCRBYReindex/update the document
Fuzzy / typoYou must implement it yourselfNo (your own logic)Built-in fuzzy option
MemoryCan be optimized (top-K per node)A ZSET per prefix, more memoryFST is compact, kept in heap
ScalingPrefix-based sharding by yourselfRedis ClusterShards + replicas
Best forGoogle-scale, ultra-low latencyTrending queries, simple setupCatalog/product name suggestions

21.5 When to choose which

  • Redis ZSET: you want to build quickly and need live updates of trending/popular queries.
  • ES completion suggester: you already have Elasticsearch and want to suggest product names/brands with fuzzy.
  • Custom Trie: very large scale and strict latency (<10 ms), with a dedicated team.
  • Algolia: you want a managed solution with no infra.
  • Always add client debounce + CDN/browser caching, whatever the backend is.

21.6 Real-world example

Real world: Swiggy/Zomato dish search typeahead (a hypothetical scenario)

  1. The user types 'bir'; after a 200 ms debounce the app sends /suggest?q=bir.
  2. The request checks the CDN/edge cache - the result for a popular prefix like 'bir' is cached city-wise.
  3. On a cache miss the suggest service runs ZREVRANGE suggest:blr:bir 0 9 in Redis - 'biryani', 'birthday cake' and so on.
  4. Results are re-ranked by the personalization layer: the user ordered Hyderabadi biryani earlier, so it goes up.
  5. The response comes in ~30-50 ms; the user selects 'biryani' and the full search runs.
  6. Every search event goes to Kafka; a Flink job updates query counts every 5 minutes (ZINCRBY).
  7. At night a batch job removes old, less popular entries and trims the ZSET size to top-N.

21.7 Interview tips

  • Common mistake: sending a request on every keystroke without debounce - 5-10x useless load on the backend.
  • Common mistake: running LIKE 'bir%' on the main search DB - slow at scale. Not filtering offensive/blocked words is also wrong - it can damage the brand's image.
  • Interview tip: be sure to mention precomputed top-K at each trie node and the offline rebuild pipeline.
  • Numbers worth quoting: target latency < 100 ms per keystroke, debounce 100-300 ms, trie lookup O(prefix length).