Web fundamentals, an interactive architecture walkthrough

Search autocomplete (typeahead): how the architecture works

How search autocomplete answers in milliseconds: prefix indexes, caching, offline ranking from query logs, trending queries and policy filtering.

This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate.

19 components, 19 connections, 13 steps. Updated 27 October 2026.

Interactive diagram

Overview

Search autocomplete suggests completions as a person types, usually after every keystroke, so it has to answer in a few tens of milliseconds and handle many more requests than the search itself. The serving path is read-only: an in-memory prefix index maps each prefix to its best completions, with a cache in front and a few merged-in signals (what is trending, what this user searched before). Rankings come from a separate offline pipeline that counts submitted queries, filters them for policy and privacy, and builds a new index.

Trade-offs and what changes at scale

Precomputing the top completions per prefix makes lookups fast but makes updates expensive and the index stale between builds, so a small fast path handles trending queries. Sharding by prefix is natural but uneven, because some starting letters are far busier than others; shards are split by observed traffic. Ranking by raw popularity is simple, while time decay, personalisation and language or location context improve relevance and cost more to compute and cache. Suggestions can surface sensitive or harmful text, so filtering and a minimum-count threshold are product requirements, not extras. Typo tolerance (fuzzy matching) widens the lookup and costs memory. Elasticsearch's completion suggester and Lucene's FST-based suggesters are real examples of the in-memory approach. This is a simplified teaching model based on public information, not Google's or any company's actual design.

How it works, step by step

The walkthrough above, as text. Each step lights up the components named under it.

  1. The user types. The search box waits a short moment between keystrokes (debouncing), skips very short prefixes and reuses answers it already fetched for earlier prefixes. A request goes first to the Edge Cache, which holds answers for popular prefixes for a few seconds.

    Components Edge CacheVia GET suggest

  2. Only a cache miss reaches the Suggestion Service. Typing patterns are heavily skewed towards a small set of short prefixes, so the edge absorbs a large share of the traffic, and a prefix with a wrong or stale answer is cached only briefly.

    Components Suggestion ServiceVia miss

  3. The service asks the Prefix Index for the best completions of the prefix. Each shard holds an in-memory structure (a trie, or a finite-state transducer as in Lucene) where each prefix leads straight to its highest-ranked completions, so a lookup costs the length of the prefix, not a scan of all queries. Shards are split by prefix range, with busy ranges split further.

    Components Prefix IndexVia prefix lookup

  4. The service also checks the Fresh Suggestions cache for queries that have only just become popular, such as breaking news, which the slower index build has not seen yet. They are merged in with the index results.

    Components Fresh SuggestionsVia trending

  5. For signed-in or recognised users it reads recent searches from the User History Store and boosts matching ones. Public descriptions of search autocomplete say predictions can reflect location and a user's earlier searches, and that users can delete those.

    Components User History StoreVia recent searches

  6. Before returning, the service removes anything the Policy Filter blocks (abusive, dangerous or legally removed predictions), reranks the merged list, and returns a handful of suggestions. The same filter runs offline too, so a blocked term is unlikely to reach the index.

    Components Policy FilterVia filter

  7. When the user submits a search, it goes through the gateway to the Search Service, which runs the real search. Selecting a suggestion and typing the full query end up here as the same kind of request.

    Components Search Service, Query Log, User History StoreVia search

  8. Submitted queries stream to the Aggregation Job, which counts them per time window and applies decay, so recent popularity counts more than old. Low-count queries are discarded, which also helps keep rare personal strings out of public suggestions.

    Components Aggregation JobVia consume

  9. The job checks candidate queries against the Policy Filter and drops blocked terms. Filtering at build time and again at serve time means a rule change takes effect immediately, without waiting for the next index build.

    Components Policy FilterVia drop blocked terms

  10. The Index Builder turns the cleaned counts into a new index snapshot per shard: for each prefix, the top completions by score. Building offline keeps the serving path read-only, which is what makes it fast and simple to replicate.

    Components Index BuilderVia counts

  11. The new snapshot replaces the old one on each replica, with the previous version kept so a bad build can be rolled back. Builds run on a schedule (hourly or daily, for example), so the main index is always a little behind real searches.

    Components Prefix IndexVia swap snapshot

  12. A faster path watches the same log for queries whose rate jumps within minutes and publishes them to the Fresh Suggestions cache with a short expiry, closing the gap between a news event and the next index build.

    Components Trending Detector, Fresh SuggestionsVia consume

  13. Observability tracks time from keystroke to suggestion (it needs to feel instant), edge hit ratio, index age and the share of searches that begin by selecting a suggestion.

    Components Observability, Index Builder, Edge CacheVia metrics

Sequence diagram

The same walkthrough as a UML sequence diagram, one lane per layer or group (14 components in all), left to right in the order a request reaches them, numbered by step. A loop on a lane is a step that stays inside that group. Solid arrows are synchronous calls, dashed are asynchronous.

Search autocomplete (typeahead): sequence diagram of the walkthroughClientsEdgeServing PathSearchLearningPipelineObservabilityGET suggest1miss2prefix lookup3trending4recent searches5filter6search7log query7save query7consume8drop blocked terms9counts10swap snapshot11consume12publish hot terms12metrics13metrics13hit ratio13

Key components

Edgelayer

  • API Gateway: TLS, auth, rate limiting
  • Edge Cache: short-lived answers for popular prefixes

Serving Pathdomain

  • Fresh Suggestions: recent trending queries, short expiry (redis)
  • Policy Filter: blocklist, legal removals, sensitive terms
  • Prefix Index: in-memory trie or FST with top completions per prefix
  • Suggestion Service: look up, merge, filter, rerank
  • User History Store: recent searches per user

Learning Pipelinedomain

  • Aggregation Job: counts queries per window with decay and thresholds
  • Index Builder: builds a new index snapshot per shard
  • Query Log: submitted searches (kafka)
  • Trending Detector: finds queries rising sharply in minutes

Searchdomain

  • Search Service: runs the full search, records the query

Observability

  • Observability: latency, keystroke-to-suggestion time, freshness

Clientslayer

  • Search Box: debounced keystrokes, local prefix cache

Sources

Public writing this explainer draws on. Read these for what the real systems actually do.

Make it yours

Copy this diagram and its walkthrough into your own workspace, then change anything: swap Postgres for DynamoDB, add a cache, rewrite the narration. Free, and it uses no AI credits.

This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate. Real systems differ in the details. Browse the library.