Requirements and Resource Estimation
In one line: this estimation is the first in the module to doubt itself. Watching where the doubt stops is more instructive than any of the three answers it produces.
Requirements
Functional: suggest the top N frequent and relevant terms for the user's input.
| Non-functional | Detail |
|---|---|
| Low latency | Under 200 ms, since the average time between keystrokes is 160 ms |
| Fault tolerance | Provide suggestions even if individual components fail |
| Scalability | Support an increasing number of users and queries over time |
Storage
Of 3.5 billion daily queries, 2 billion are unique and need to be stored. Each query is 15 characters on average at 2 bytes per character:
2,000,000,000 x 15 x 2 = 60 GB/day 60 GB x 365 = 21.9 TB/year
Multiplying unique-per-day by 365 confuses a set with a stream
Both lines are arithmetically correct and the second one measures something that does not exist.
The trie stores a set of distinct queries. Multiplying a daily count of unique queries by 365 assumes that no query on any day appears on any other day — that today's two billion distinct queries and tomorrow's two billion are entirely disjoint.
They are not. "weather", "youtube", "translate" are unique today and unique tomorrow, and you store them once:
Treating queries as a STREAM: 2B/day x 365 = 730B entries -> 21.9 TB Treating queries as a SET: cumulative distinct grows much slower
Query distributions are heavily long-tailed: a stable head of common queries repeats daily, and a genuinely novel tail — new names, events, products — accumulates. Only the tail contributes to year-over-year growth.
So 21.9 TB is an upper bound assuming zero repetition, which is the opposite of what a typeahead system relies on. The whole premise of ranking by frequency is that queries repeat.
When storage holds a set, you cannot annualize a daily count by multiplication. That is a general trap: the calculation is right for logs, right for messages, and wrong for anything deduplicated.
The related figure worth noting is that 60 GB fits in memory on one machine — which matters, because Lesson 4 requires the index to be RAM-resident.
Bandwidth
3.5 billion queries x 15 characters = 52.5 billion characters/day 52.5B / 86,400 = 607,639 characters/second 607,639 x 2 bytes x 8 = 9.7 Mb/s incoming 9.7 x 10 suggestions = 97 Mb/s outgoing
Under 100 Mb/s — and the outgoing multiplier is the interesting part
Both figures verify. The system moves less than a tenth of a gigabit in each direction, which is nothing.
The 10× outgoing multiplier is worth naming because it is a fan-out most people miss: each keystroke sends one prefix and receives ten suggestions of similar length. So the response is an order of magnitude larger than the request — inverted from most systems, where requests are small and responses vary.
And 607,639 characters per second is the real request rate. Hold onto it; the server section is about to ignore it.
Servers — three answers
821,000, then 164,000, and the table says 9
The chapter computes this three times.
First attempt. Using the DAU-as-RPS convention on the character count:
52,500,000,000 / 64,000 = 820,312 -> "821 K servers"
Then the design does something no other chapter in this module does — it doubts itself:
Note: The initial estimate of 52.5 billion requests per second is unrealistic. However, on average, a person types three to four characters per second.
Second attempt. Revising to three characters per second:
3,500,000,000 x 3 / 64,000 = 164,062 -> "164 K servers"
And the interactive table, in the same lesson, reports:
Number of Servers (uniform requests) = 9
Three answers, and the table is right.
The correct derivation is the one the bandwidth section already performed:
52.5 billion characters/day / 86,400 = 607,639 characters/second 607,639 / 64,000 = 9.5 servers
About nine machines, against a published 164,000.
The revision fails on a substitution error, and it is worth naming precisely: "assuming 3.5 billion users and a peak where each types roughly three characters per second." But 3.5 billion is searches per day, not users — and even if it were users, it assumes all of them typing simultaneously and continuously.
Prose #1: 52.5e9 RPS -> 821,000 servers (86,400x too high) Prose #2: 10.5e9 RPS -> 164,000 servers (17,280x too high) Table: 607,639 RPS -> 9 servers (correct)
Doubting a number is most of the skill; the rest is identifying which input was wrong. This chapter does the first half — genuinely more than any other source in the module — and then substitutes a second wrong quantity for the first.
The lesson to carry: when you revise an estimate, check that the new input is the same kind of quantity as the one it replaces. Searches per day and concurrent users are not interchangeable.
And nine is still an over-estimate, because of debouncing
Lesson 8 introduces debouncing: the client only contacts the server if the user pauses typing, with a suggested threshold of 160 ms.
That is exactly the stated average inter-keystroke interval — so debouncing at that threshold suppresses roughly half of all keystrokes before they become requests.
Which means the effective request rate is meaningfully below 607,639 per second, and nine servers is itself generous. Add Lesson 8's input threshold (wait for a few characters before the first request) and client-side caching, and the number falls further.
The client-side optimizations are not polish; they are the largest capacity lever in the system — because the request rate is driven by keystrokes, and the cheapest request is the one never sent.
| Quantity | Published | Assessment |
|---|---|---|
| Storage/day | 60 GB | Correct — and it fits in memory on one machine |
| Storage/year | 21.9 TB | Confuses a set with a stream — assumes zero repetition across days |
| Incoming bandwidth | 9.7 Mb/s | Correct |
| Outgoing bandwidth | 97 Mb/s | Correct — a 10x fan-out from ten suggestions |
| Servers | 821K, then 164K | ~9, which the chapter's own table reports |
Building blocks — and one is doing more work than the list implies
The design names databases (store query prefixes), load balancers, and caches (store the top N suggestions).
The cache is the load-bearing one, and Lesson 4 explains why: the index must be in memory because a disk read alone would consume the latency budget. So the cache is not an accelerator over a database — it is the serving layer, and the database exists for durability and rebuild, not for reads.
That is the same relationship the newsfeed chapter's materialized view had: a store the system reads from, backed by a store it recovers from.
Key takeaway
21.9 TB/year confuses a set with a stream — annualizing a daily unique count assumes zero repetition across days, which contradicts the very premise that queries repeat often enough to be ranked by frequency. The server section produces 821,000, then 164,000, then 9 in one lesson, and the interactive table has the right one: 607,639 characters per second divided by 64,000. Uniquely in this module, **When you revise an estimate, check the new input is the same kind of quantity as the one it replaces. And nine is still generous, because debouncing at the 160 ms threshold suppresses roughly half of all keystrokes.
The rate is driven by keystrokes, not searches, and keystrokes are generated on the client — which is why the client is where most of the traffic is removed.
Interview signal by level
| Level | What a strong answer sounds like |
|---|---|
| L4 | "3.5 billion queries at 15 characters is 52.5 billion keystrokes a day, about 10 Mb/s in and 100 Mb/s out, with 60 GB of unique queries per day." |
| L5 | Converts to a rate: "52.5 billion characters a day is about 600,000 requests per second — that's roughly ten servers, not thousands. And the index is only 60 GB, which fits in memory." |
| Staff+ | Catches all three: "the estimate gives 821,000 servers, then revises to 164,000, and its own table says 9 — the table is right, because the real rate is 607,000 characters per second. The revision substitutes searches-per-day for users, which is a different quantity. I'd also flag that 21.9 TB a year annualizes a daily unique count, which assumes no query repeats across days — the trie stores a set, and the whole ranking premise is that queries repeat. And nine servers is generous anyway, because debouncing at 160 ms suppresses about half the keystrokes before they become requests." |
Next: the high-level design and the two APIs.