Section 4: A Million Identical Questions - API Design (with pushback)
Executive Summary: The typeahead API is three small contracts: a per-keystroke suggestion call, a once-per-session history call, and a batched event beacon. The keystroke call is a plain HTTP GET that says nothing about who is asking, so a CDN can answer most of the ~1M QPS peak. We write Maya's request in full, pin down normalization and the cache key, handle out-of-order responses, and take four pushbacks: WebSockets, POST, server-side personalization, and the index version in the URL.
The interviewer caps the marker: "Show me the call the search box makes." I start from Section 3's headline, not a list of endpoints: about 8 requests per search, ~1M QPS at the edge, and most of them the same question asked by millions of people ("what follows chi?"). So the contract's first job is to let identical questions get identical answers from a cache.
The Keystroke Call
Here is Maya's request, sent from her phone after she types chicago mara:
GET /v1/suggest?q=chicago%20mara&locale=en-US&client=mobile&v=2026-10-11a
200 OK
Content-Type: application/json
Content-Encoding: gzip
Cache-Control: public, max-age=60, s-maxage=120
{
"q": "chicago mara",
"indexVersion": "2026-10-11a",
"suggestions": [
{ "text": "chicago marathon results", "type": "query" },
{ "text": "chicago marathon 2026", "type": "query" },
{ "text": "chicago marathon route", "type": "query" },
{ "text": "chicago marathon tracker", "type": "query" },
{ "text": "chicago marathon road closures", "type": "query" }
]
}
(Ten entries in practice; trimmed here.) What's deliberate:
qis echoed back so the client can drop stale responses.typeexists from day one, though every entry is"query"today. Section 12's entity suggestions arrive as a new type, not a new endpoint.- It's tiny: ~1 KB uncompressed, ~400 B gzipped, so peak edge egress is 1 GB/s ≈ 8 Gbps.
Cache-Control: public, max-age=60, s-maxage=120. The CDN keeps it 120 s. The browser keeps it up to 60 s, counted from when the origin produced it, because the CDN passes itsAgeheader through, so the two layers together never hold a copy longer than 120 s. That keeps the 2-minute line in Section 2's freshness budget honest. (Backspacing is free anyway: the client's own prefix cache answers it.)- Safe search is in the key too: a non-default setting adds
&safe=off, so the default URL stays shared.
Notice what's missing: a cookie, a user id, an auth header. That's on purpose, and it takes two deliberate steps. The client calls fetch with credentials: "omit" (or the endpoint lives on a cookieless host such as suggest.example.com), and the CDN strips Cookie and leaves it out of the key, so a stray cookie can never split the cache or reach the origin. The pushback goes straight at this.
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson