Requirements
In one line: two of the non-functional requirements here cannot both be satisfied at this scale. Lesson 10 proves it; this lesson is where you should start to suspect it.
Functional requirements
| Requirement | Detail |
|---|---|
| Short URL generation | Generate a unique short alias for a given URL |
| Redirection | Redirect a short link to its original URL |
| Custom short links | Allow users to create custom short links |
| Deletion | Delete a short link with proper authorization |
| Update | Update the long URL associated with a short link, with proper authorization |
| Expiry time | A default expiration time, but users may set a custom one |
Custom short links are the requirement that complicates everything
Five of these six are trivial. Custom short links is not, and it forces machinery into the design that would otherwise be unnecessary.
Without custom aliases, the system is beautifully simple: a sequencer produces a unique integer, an encoder makes it readable, and collisions are impossible by construction because encoding is a bijection.
Add custom aliases and three problems appear at once:
Collisions become possible. A user asks for /coffee, and someone may already have it — so every custom request needs an availability check against the database.
The ID space becomes partially occupied by strings you did not generate. If a user claims /coffee, the sequencer must never later produce the integer that encodes to coffee. Lesson 11 shows the design's answer: decode the custom alias back to base-10 and mark that ID used.
Uniqueness is no longer free. It now depends on a shared, consistent record of which IDs are taken — which is exactly the coordination the sequencer design was avoiding.
One optional feature converts a collision-free design into one that needs collision detection. That is worth noticing generally: features that let users choose identifiers always cost more than features that assign them.
Update is riskier than it looks
"Allow users to update the long URL associated with a short link."
Reasonable, and it means a short URL is a mutable pointer rather than a permanent alias. Three consequences the design never addresses:
Cache invalidation. Lesson 3 sizes a 66 GB cache of hot mappings. An update must invalidate the entry — otherwise the old destination is served until the entry ages out.
A link you shared can silently change destination. Someone posts a shortened link to a news article; the owner later repoints it. Every historical share now goes somewhere else. That is a genuine abuse vector — a link that passes moderation and is then repointed at malware.
It undermines caching at every layer. Browsers, proxies, and the redirect status code itself. Which raises a question the chapter never asks: is the redirect a 301 or a 302?
301 Moved Permanently -> browsers CACHE it, so later clicks never reach you 302 Found -> every click reaches your servers
A 301 is faster for users and cheaper for you — but you lose click analytics and the ability to update, because the browser has memorized the destination. A 302 keeps control and pays for every click.
Given an update requirement, the redirect must be a 302 — and that decision doubles as the reason the read rate is 100× the write rate.
Expiry has an unusual justification
Note: The system deletes expired short URLs after five years, even though they are not reused. Retaining them indefinitely would cause the datastore's search index to grow continuously, which increases query time and overall latency.
Two things worth noticing.
Deletion is for index size, not storage. Lesson 3 puts five years of data at 6 TB — trivially cheap to keep. The stated reason is that a growing index slows queries, which is a more sophisticated argument than "we would run out of space."
"They are not reused" is a deliberate choice. You could reclaim expired IDs and hand them out again, which would extend the ID space indefinitely. The design refuses — and it is right to, because reusing an identifier means an old link suddenly resolves to someone else's destination. Identifier reuse in a public namespace is a security problem, not an optimization.
And Lesson 9 shows reuse is unnecessary anyway: the sequencer's lifetime is 7.7 billion years.
Non-functional requirements
| Requirement | Detail |
|---|---|
| Availability | Any downtime causes redirections to fail. This requires significant fault tolerance, as the service's domain is part of every generated URL |
| Scalability | Scale horizontally to handle increasing traffic |
| Readability | Generated short links must be easy to read and type |
| Latency | Redirection must happen with very low latency |
| Unpredictability | Short URLs should not be guessable. Sequential IDs would create a security risk |
Readability and unpredictability pull in opposite directions
Hold these two side by side:
Readability: "short links must be easy to read and type" — which means short.
Unpredictability: "should not be guessable" — which means sparse.
Short means a small space of possible strings. Sparse means most of that space must be unused. And the system needs to store 12 billion URLs.
Those three cannot all hold, and Lesson 10 does the arithmetic. The preview:
6 characters -> 58^6 = 38 billion possible strings 12 billion stored -> 31.5% of the space is occupied
Roughly one random guess in three would hit a real URL. That is not "difficult to predict" — it is trivially enumerable.
The chapter's own answer to unpredictability is to "select an ID at random from its assigned range" rather than sequentially. That helps against sequential enumeration but does nothing about density: if a third of all 6-character strings are live, randomness of assignment is irrelevant to an attacker who simply tries strings.
Worth flagging now because the chapter states both requirements confidently and never brings them into contact. When two requirements constrain the same quantity in opposite directions, check whether the constraint is satisfiable before designing to both.
The availability argument is unusually well put
"Any downtime will cause URL redirections to fail. This requires significant fault tolerance, as the service's domain is part of every generated URL."
That last clause is the sharp part, and it is a genuinely distinctive availability argument.
For most services, an outage means users cannot use your product for a while. Here, an outage means every link anyone has ever shared, anywhere, is broken — in emails sent years ago, in printed material, in other people's databases.
The links are outside your control and permanent. You cannot ask the internet to re-share corrected URLs.
That has two consequences the chapter draws and one it does not:
Fault tolerance must be high — replication, GSLB, multi-datacenter, all of which Lesson 12 covers.
The domain can never change. It is embedded in billions of artifacts you do not own.
And it makes shutdown impossible. The disadvantages section notes "if the service shuts down, all associated links break" — which means a URL shortener has an unusually strong obligation to outlive its own commercial usefulness.
When your identifier is embedded in artifacts you do not control, availability becomes a permanent obligation rather than a service level.
302 rather than 301 is the small decision with the largest consequences. A 301 tells the browser the mapping is permanent, so it stops asking — you can never revoke, expire, or re-point a link, and you never see the click. Expired codes should return 410 Gone rather than 404: "this existed and no longer does" is different information from "this never existed."
Key takeaway
Custom short links is the one functional requirement that complicates everything — it converts a collision-free design into one needing collision detection and a shared record of used IDs. Update makes a short URL a mutable pointer, which forces a 302 rather than a 301 and creates a real abuse vector. Expiry exists for index size, not storage, and IDs are deliberately not reused, because identifier reuse in a public namespace is a security problem. And readability and unpredictability constrain the same quantity in opposite directions — short means a small space, unguessable means a sparse one, and 12 billion URLs make 6 characters 31.5% occupied. The availability argument is unusually sharp: the domain is embedded in artifacts you do not control, which makes availability a permanent obligation.
Next: the estimation, and the largest contradiction in the module.