Library / Case Studies
Amazon Architecture - High Scalability -
This is a wonderfully informative Amazon update based on Joachim Rohde's discovery of an interview...
By High Scalability engineers · High Scalability · Added 2026-10-12
All content belongs to High Scalability engineers / High Scalability. We only link to it and give credit. Report a problem
Learn this case study
About 37 min left. Your work is saved as you go.
What you are about to study
High Scalability explains a real system. You should know the basics: caching, queues and replication.
Ideas you will meet
- Distributed Systems
- Consensus, time, failure and the fundamentals of scale-out.
What we already know about this
Our own lessons on these ideas. Read them here before you start, so it makes sense.
Classic System Designs · 10 minDesign search autocompleteSuggest completions as the user types, within a tenth of a second: tries, top-k per prefix and how suggestions are updated.Read here
The problem
As a user types "syst", show a handful of likely completions: "system design", "systemd", "system of a down". The suggestions must appear almost instantly (under about 100 ms) or they are useless, and they should reflect what people actually search.
Requirements
- Fast: respond within ~100 ms.
- Return the top 5 to 10 completions for the typed prefix, ranked by popularity.
- Handle high volume (a request per keystroke).
- Updated regularly with new trends.
The core data structure: a trie
A trie (prefix tree) stores words along paths of letters, so all words that share a prefix share a path.
100%Figure SDA-CSD-09-1 · Trie with word frequencies · © forcsguy.com
To find completions for a prefix, walk to its node, then look at everything beneath it. Doing that on every keystroke is too slow for a big trie, so we precompute: at each node store the top k most popular completions for that prefix.
100%Figure SDA-CSD-09-2 · Top-k completions cached per prefix · © forcsguy.com
Now a query is: walk the prefix (a few steps), read the stored list. That is fast and independent of how large the subtree is.
From raw queries to counts
100%Figure SDA-CSD-09-3 · Counting queries into a frequency table · © forcsguy.com
Two services
100%Figure SDA-CSD-09-4 · Online query path and offline trie build · © forcsguy.com
Query service (online)
- Receive the prefix.
- Look it up in the in-memory trie or a prefix cache.
- Return the top suggestions.
Data pipeline (offline)
- Search queries are logged.
- A periodic job (hourly or daily) aggregates counts per query, filtering out spam and abusive terms.
- A builder creates the new trie with top-k lists.
- The new version is published to the serving machines and swapped in.
Real-time updates for every search would be costly and unstable. For breaking trends you can add a small fast path for recent spikes.
Looking up a prefix in the trie
100%Figure SDA-CSD-09-5 · Autocomplete lookup on a trie with cached top lists · © forcsguy.com
When one query's count changes, every node on the path above it must refresh its stored list, which is why the trie is rebuilt in a batch rather than edited per search:
100%Figure SDA-CSD-09-6 · Updating a count touches all ancestors · © forcsguy.com
100%Figure SDA-CSD-09-7 · A trie stored as key-value pairs · © forcsguy.com
100%Figure SDA-CSD-09-8 · Filtering unwanted suggestions · © forcsguy.com
100%Figure SDA-CSD-09-9 · Sharding the trie by prefix · © forcsguy.com
Making it faster and bigger
- Client side: wait a short pause after typing (debounce), skip very short prefixes, and cache previous responses in the browser.
- Server side: keep the trie in memory; cache hot prefixes; set a CDN or edge cache for the most common ones.
- Limit prefix length (for example 50 characters) to bound work.
- Shard the trie across machines, for example by the first letters, balancing by traffic not by alphabet (some letters are far more common).
- Replicate the serving tier for availability.
The numbers and the trie's cost
Each keystroke is a request, so 10 million users doing 10 searches of about 20 keystrokes is on the order of 24,000 requests per second (about double at peak), while only roughly 0.4 GB of new query text arrives per day. The trie's walk to a prefix is proportional to the prefix length, then reading its children and sorting them would be slow; two changes make lookup effectively constant time: cap the prefix length, and store the top few suggestions on every node (trading space for time). The cost moves to updates: changing one count means refreshing the cached lists on every ancestor up to the root, which is why the trie is normally rebuilt in a batch (say weekly) from aggregated logs and swapped in, rather than edited per query.
Storing the trie. Either serialise each weekly snapshot into a document store, or flatten it into a key-value store where each prefix is a key and the node's data is the value. Serve from a distributed cache; on a miss, fill the cache from the store.
Log less. Sample the query log (record one in N) because logging every keystroke-level request is costly and top results are statistically stable.
Take-down. Put a filter layer in front of the cache to hide unsafe suggestions immediately, and delete them from the data before the next rebuild.
Variants. Different countries can have their own tries (even served from a CDN); other languages need Unicode in the nodes; trending queries need a faster path, such as stream processing and a ranking that weights recent searches more.
Quality details
- Ranking can combine popularity, recency and personalisation.
- Safety: filter offensive or sensitive suggestions.
- Typos: optionally tolerate small spelling errors.
- Languages: tokenisation and ordering differ per language, so plan for it early if you need it.
Worked numbers: does the whole thing fit in memory?
Say the system serves the 10 million most common prefixes, storing the top 5 suggestions for each at roughly 100 bytes (five short strings plus scores). That is about 1 GB, comfortably inside one machine's memory, and a few GB with overhead. Even 100 million prefixes is only about 10 GB. So the "answer from memory, rebuilt in the background" design is realistic; no search over a huge dataset happens per keystroke.
Latency budget for a 100 ms target as seen by the user: the browser debounce is an intentional pause (not part of the budget); network round trip 30 to 50 ms; edge or load balancer 5 ms; service 5 to 10 ms to hash the prefix and read the cached list; response and render 10 ms. There is little room for anything slower, which is why the lookup must be a single key read.
Request volume: 10 million users x 10 searches x about 20 keystrokes is 2 billion prefix lookups a day, about 24,000 per second on average. Debouncing (waiting about 150 ms after the last keystroke) and not querying for very short prefixes can cut that by half or more.
100%Figure SDA-CSD-09-10 · Debounce and ignore late answers · © forcsguy.com
Ranking: popular, recent and personal
Raw popularity is a good start but has two problems. It favours old favourites over trending queries, and it is the same for everyone. A common improvement blends signals:
score = popularity x decay + trending boost + personal boost- Decay: weight recent searches more, for example by halving a query's weight every day or week, so a sudden event rises quickly and fades.
- Trending: a fast path watches a stream of recent queries and lifts those whose rate jumps compared with their normal level.
- Personal: a user's own recent searches, kept separately (and cached per user, not in the shared trie).
- Safety and quality: filter offensive or illegal suggestions and anything with too few searches to be useful or private.
100%Figure SDA-CSD-09-11 · Blending slow and fast ranking signals · © forcsguy.com
Mistakes people make
- Searching the data per keystroke. Precompute the top suggestions per prefix.
- Ignoring out-of-order responses. A slow response for "sy" arriving after "syst" overwrites the list with stale results.
- Putting personal data in the shared cache. Keep personal suggestions out of anything shared across users.
- Forgetting normalisation. Case, accents, extra spaces and different Unicode forms must map to the same prefix.
- No filtering. Autocomplete amplifies whatever people type, including offensive or private terms.
- Rebuilding on every search. Rebuild in batches and swap versions atomically.
Try it yourself
Build the tiny search engine lab for the index side, and read the query understanding lesson for how typed text is cleaned before it is matched.
Real-world reading
Related reading
- YouTube ArchitectureHigh ScalabilityCase Studies
- Hello Interview: System Design in a HurryHello InterviewCourses
- Hello Interview: System Design WalkthroughsEvan King & Stefan Mai · Hello InterviewYouTube
- Meta Engineering BlogMeta Engineering · MetaBlogs
Show 6 moreShow fewer
- Cloudflare Learning Center: What is a CDN?CloudflareDocumentation
- Solving Remote Build Cache Misses (2 parts) at SoundCloudSoundCloud engineers · SoundCloudCase Studies
- Scaling Memcache at Facebook (paper)Nishtala et al. · Meta (Facebook)Papers
- Reduce Memcached Memory Usage by 50% at TrivagoTrivago engineers · TrivagoCase Studies
- Amazon Architecture - High Scalability -High Scalability engineers · High ScalabilityCase Studies
- LINE Engineering BlogLINE engineers · LINEBlogs
Go deeper on this
A path through videos, articles, other case studies and code on the same ideas as Amazon Architecture - High Scalability -.
Warm upGet the vocabulary first.
Books · Free from the author
Concurrent and Distributed Systems (Cambridge lecture notes)
Eight lectures on time, broadcast, replication, consensus and transactions, with notes, slides and video. Free from the author under CC BY-SA.
University of CambridgeIntermediate
Books · Free from the author
Computer Networks: A Systems Approach
How networks are built and why: protocols, routing, congestion control and the internet's architecture. The authors publish it free online under CC BY 4.0.
Systems ApproachIntermediate
WatchHow others solve the same problem, on video.
Videos belong to their creators and play from YouTube. More on YouTube (opens in a new tab)
ReadEngineers explain it in their own words.
Blogs · Free from the author · Read here
Scalable Web Architecture and Distributed Systems
A full chapter on the building blocks of large websites: availability, performance, reliability, scalability, caches, proxies, indexes, load balancers and queues. Free to read here under CC BY 3.0.
The Architecture of Open Source ApplicationsBeginner40 min
Papers · Read here
Facebook’s photo storage
This paper describes Haystack, an object storage system optimized for Facebook’s Photos application. Facebook currently stores over 260 billion images, which translates to over 20 petabytes of data.
USENIXIntermediate
See it in another companyThe same ideas, a different system.
Case Studies · Read here
Aroma: Using ML for Code Recommendation at Facebook
Thousands of engineers write the code to create our apps, which serve billions of people worldwide. This is no trivial task—our services have grown so diverse and complex that the codebase contains…
FacebookIntermediate
Case Studies · Read here
Brooklin: Distributed Service for Near Real-Time Data Streaming at LinkedIn
Brooklin—a distributed service for streaming data in near real-time and at scale—has been running in production at LinkedIn since 2016, powering thousands of data streams and over 2 trillion messages per day. Today, w...
LinkedInIntermediate
Read the codeSee how it looks when it is real.
GitHub
Engineering Blogs
A huge directory of company engineering blogs to learn from real production systems.
kilimchoiIntermediate
GitHub
Awesome Scalability
Curated reading list of articles on the architecture of scalable, reliable systems.
binhnguyennusIntermediate
Keep learning
Loading community…