Search Autocomplete — Masterclass
Three additional artifacts a Staff/Principal candidate should be able to produce for this problem: an Architecture Decision Record, a business-driven design exercise, and a production incident scenario.
1. Architecture Decision Record
The format working architects use to document a decision so future teams understand context, options, and reversal conditions.
In-process mmap FST shards + prefix-hash sharding + Flink 60s-window trending injection + CDN edge caching for top-1000 prefixes + client-side debouncing + 3-floor server derivation (ingress/query/rebuild) — over Elasticsearch Completion Suggester (L5 pattern), custom Trie, managed Algolia Places, or Google Cloud Autocomplete API.
- 300K-800K QPS peak (baseline 150K)
- 500M distinct query corpus; ~50-100 bytes avg per query
- p99 latency: <20ms end-to-end (browser → suggestion visible)
- p99 latency: <10ms server-side (leaves 10ms for network + client render)
- Trending: 'celebrity death' or 'earthquake tsunami' must surface within 30-60s of viral spike
- Corpus freshness: nightly rebuild is fine for baseline; trending overlay for real-time
- Availability: 99.99% (search box is user-facing; degrade to 'no suggestions' on failure, not error)
- Cost bound: $15K/mo compute at scale (autocomplete is high-QPS but low-per-query cost)
- Team: 4 engineers, 1 with FST/Lucene experience — critical constraint
- Privacy: sensitive queries (medical, legal, financial) MUST NOT leak to trending
Custom in-process FST + Flink trending + CDN edge (chosen)
- Sub-3ms server-side p99 (in-mem FST walk is 1-2ms; trending merge adds 1ms)
- 5-10x memory efficient vs Trie (FST shares suffix state via finite-state automaton)
- Flink 60s window catches viral events in 20-30s
- CDN edge caches top-1000 prefixes for 15s (60-80% QPS bypass origin)
- 3-floor server derivation isolates blast radius (ingress DDOS ≠ query kill ≠ rebuild kill)
- Client debouncing kills 60-70% of load with no UX impact
- Cost ~$12K/mo compute at 500K QPS — well under budget
- 3-6 months of custom FST-service engineering before first production traffic
- Requires 1 engineer with Lucene/FST expertise — scarce hire
- FST rebuild is 2-4 hours for 500M queries; must be nightly batch not real-time
- Trending overlay requires Flink infrastructure (Kafka + Flink + Redis)
Elasticsearch Completion Suggester (L5 pattern extended)
- Uses Lucene FST internally — same underlying data structure
- 5-30ms p99 (works fine for <200K QPS; degrades at higher scale)
- Standard ES ops, no custom FST service to build
- Built-in fuzzy match, snapshot backup, monitoring via Kibana
- 5-30ms p99 is AT OR ABOVE our 20ms budget — no margin
- Coord + master + JSON serialization overhead adds 5-10ms baseline
- Cannot use edge PoPs — all queries hit central cluster
- Adding trending overlay requires custom code anyway
Managed Algolia Places / Search
- Sub-10ms p99 globally (Algolia has world-class autocomplete)
- Zero ops burden
- Excellent DX with instant-search UI kits
- Cost: $1.50 per 1000 operations × 800K QPS peak × 86400s × 30d = $3.1M/mo at list; $300-600K/mo at enterprise discount
- Cost trajectory scales LINEARLY with QPS — becomes prohibitive at growth
- No custom analyzers, no custom ranking, no trending injection API
- Vendor lock-in on ranking → we can't tune 'why does query X rank above query Y?'
Google Cloud Autocomplete API
- Google's own autocomplete infrastructure — best-in-class
- Multi-language + world knowledge built-in
- Sub-5ms p99 globally
- Cost: $0.75-$1.50 per 1000 requests × 800K QPS = $1.5-$3M/mo at list
- Corpus is GOOGLE'S corpus (web search), not OUR corpus (marketplace queries)
- Cannot inject our own queries into ranking — 'macbook m3' will suggest Google's top-K, not what OUR users searched for
- Data-residency: queries leave our infrastructure to Google
Redis sorted set per prefix (L4 pattern extended)
- Simplest possible architecture — SET/GET per prefix
- Sub-2ms p99 in-Redis latency
- Team already knows Redis
- 5-10x memory footprint vs FST (no shared-suffix compression)
- No fuzzy match without prefix expansion (which is expensive)
- Nightly rebuild only — no trending injection
- Doesn't scale past ~200K QPS on single Redis instance; Redis Cluster adds coordination overhead
Custom in-process FST + Flink trending + CDN edge + client debounce + 3-floor derivation
- Elasticsearch Completion Suggester — 5-30ms p99 too close to budget, no edge deployment
- Algolia — $300-600K/mo linear scaling with QPS is prohibitive
- Google Cloud Autocomplete — uses Google's corpus not ours, competitive intelligence leak
- Redis sorted sets — 5-10x memory waste, no trending injection, doesn't scale past 200K QPS
- Accept 3-6 months of upfront custom FST service engineering
- Accept 1 senior engineer with FST/Lucene expertise as a critical hire dependency
- Accept nightly baseline rebuild (2-4h) — no real-time corpus updates outside trending overlay
- Accept Flink operational burden — Kafka + Flink + trending Redis is 3 new operational surfaces
- Accept custom ranking model that requires ML team to tune — no plug-and-play
- Sub-3ms server-side p99 → sub-20ms end-to-end with browser render
- 5-10x memory efficiency vs Trie → 500M queries fit in 40 nodes not 200
- Trending events visible within 20-30s of viral eruption
- 60-80% of QPS bypasses origin via CDN edge cache
- Ranking becomes tunable via internal ML team — competitive advantage
- Autocomplete becomes a first-class internal service that other products can consume
- If FST-expert engineer leaves and no replacement hire → migrate to managed Elasticsearch
- If corpus shrinks below 50M queries → Redis sorted sets become viable (simpler)
- If QPS drops sustainably below 100K → Algolia enterprise deal becomes cost-competitive
- If we open a market in a language whose FST support is poor → dedicated per-locale infrastructure
2. Business constraint exercise
Given real-world constraints (team size, budget, deadline), what architecture do you propose — and how do you push back when leadership asks for the wrong thing? This teaches engineering judgment.
You are engineer #4 at a 4-year-old marketplace startup. CTO messages you Monday: 'Autocomplete is broken. Suggestions take 200-500ms to appear; users type past them. We built it 3 years ago on Elasticsearch main index (not the completion suggester). I want it FIXED in 8 weeks. Two options: (1) rewrite on Elasticsearch Completion Suggester (2 weeks, easy) or (2) hire a Lucene expert and build custom in-process FST (6 months, sub-3ms p99). CTO wants option 1. Board wants a 'best-in-class autocomplete' for the Series C pitch in 12 weeks. Which do we pick and how do you defend it?'
- 18-week deadline from CTO; 12-week board target for Series C pitch
- 2Current autocomplete: 200-500ms latency (broken — using ES main index instead of completion suggester)
- 3300K QPS peak, growing to 800K QPS in 18 months
- 4150M distinct query corpus; ~30% typos or misspellings
- 53 backend engineers on search team; NONE have FST/Lucene expertise
- 6$500K annual budget approved for search + autocomplete rebuild
- 7Existing infra: 12-node Elasticsearch cluster (main index) already running
- 8CTO preference: rewrite on ES Completion Suggester (2-week sprint)
- 9Board target: 'best-in-class' autocomplete for competitive differentiation
What do you recommend? Address: (a) whether ES Completion Suggester meets the 'best-in-class' bar for Series C pitch, (b) whether the 6-month custom-FST timeline fits the 12-week board window, (c) how to sequence a strategy that ships in 8 weeks AND positions us for 'best-in-class' by year-2, and (d) what's the real cost math including Amara-paper revenue impact.
3. Production incident scenario
You are on-call at 3:47am. p99 has spiked. Walk through the investigation, hypothesis, mitigation, and postmortem. This teaches real production reasoning — not just design.
PagerDuty alert at 8:42am ET. Major celebrity's death breaks on Twitter. Autocomplete QPS for prefix 'jo' jumps from ~500/s to ~2M/s in 90 seconds. Trending Redis is at 100% CPU, evicting entries. FST query nodes are at 95% CPU. p99 latency spiking from 8ms to 340ms. Marketing texting on-call: 'suggestions are stale — showing yesterday's celebs, not the news everyone is searching.'
- autocomplete.qps: 2.1M (baseline 300K — 7x overall)
- autocomplete.qps.by_prefix.jo: 2M (baseline 500 — 4000x this prefix)
- autocomplete.qps.by_prefix.j: 1.8M (baseline 8K — 225x this prefix)
- trending.redis.cpu_percent: 100% (saturated)
- trending.redis.evicted_keys_per_sec: 45K (was 0 baseline)
- trending.redis.hit_rate: 32% (was 98% baseline)
- fst.query_nodes.cpu_percent: 95% (was 40%)
- autocomplete.p99_latency_ms: 340 (baseline 8)
- autocomplete.p99_latency_ms.by_prefix.jo: 620 (celebrity-name prefix worst)
- cdn.edge.hit_rate: 12% (was 78% — CDN can't cache trending-hot prefix efficiently)
- flink.trending_pipeline.watermark_lag_seconds: 180 (was <10 — pipeline falling behind)
- elb.5xx_rate: 2.1% (was 0.01% baseline)
- 08:42:03 flink log: 'sliding window compute lag detected — watermark 45s behind wall clock'
- 08:42:15 trending redis log: 'MAXMEMORY-POLICY allkeys-lru evictions starting'
- 08:43:00 fst-query-node-7 log: 'walkTrie(prefix=jo) latency 34ms (baseline 1.2ms) — thread contention'
- 08:43:22 flink log: 'trending detection for prefix=jo: 4000x baseline — publishing to trending redis'
- 08:43:24 trending redis log: 'SET trending:jo EX 60 → OK (delayed 84s from event)'
- 08:43:45 alert channel: 'watchdog fires: autocomplete_p99 > 100ms for 3 consecutive minutes'
- 08:45:12 cdn edge log: 'cache-miss rate spike for prefix=j* → origin bypass',
- 08:47:00 (self-healing attempt) fst-node-3 log: 'auto-scale up: adding 8 nodes to query pool'
- 08:52:00 flink log: 'watermark caught up — pipeline back to <10s lag'
- 09:05:00 metrics: 'autocomplete.p99 back to 12ms; trending suggestions live for prefix=jo'
- Baseline FST shards (40 nodes): DEGRADED — 95% CPU, tail latency spiking
- Trending Redis: SATURATED — 100% CPU, evicting entries under memory pressure
- Flink trending pipeline: LAGGING — watermark 180s behind wall clock
- CDN edge (Cloudflare): DEGRADED — hit rate 12% (was 78%)
- Kafka query-events topic: HEALTHY (producer side fine)
- Baseline corpus rebuild (Spark): NOT INVOLVED (last rebuild 6 hours ago, next in 18h)
It's 8:44am. Traffic is at 7x baseline overall and 4000x on prefix 'jo'. What's the ONE metric that tells you 'is this a real celebrity spike vs a bot / DDoS'?
You've confirmed it's a real celebrity news spike. Give your top 3 hypotheses for WHY latency spiked, ranked by likelihood given the metrics.
Design a 60-second mitigation. Constraint: latency must return to <30ms p99 within 5 minutes. What's your action?
Postmortem the next day. Name 3 action items ranked by impact, with 'expected reduction in trending storm impact' quantified.
Draft the customer-facing status page update at T+20 minutes (after latency recovers but before all trending updates are live).
Learn these first
- FST (Finite State Transducer) — shares prefix AND suffix state, 5-10x smaller than Trie
- Amara Google 2009 paper: 100ms latency = 1% revenue lost
- Flink sliding-window trending detection (60s window / 10s slide)
- Differential privacy (Laplace noise, ε=1.0) for trending signal protection
Where this appears in the curriculum
This is the Gold Standard.
Every other system will eventually have a masterclass tab like this one. The pattern proven here — ADR + business exercise + incident scenario — scales to all 50+ problems on the platform.