Section 2: Two Systems, Two Contracts - Requirements (Functional & Non-Functional)
Executive Summary: This section turns Section 1's assumptions into promises that can be measured. The functional side is small: create, redirect, disable, and list, with four plausible features deliberately deferred. The non-functional side carries the weight. Redirects get p99 under 50 ms and 99.99 % availability, while creates get p99 under 200 ms and 99.9 %. Durability tolerates no loss at all, and freshness bounds are stated in seconds. We also explain why the two paths deserve different targets, push back on a request for five nines, and say plainly that a short code is not a secret.
The clarifications are done, and the interviewer caps the marker: "Okay. What exactly are you committing to?" The interviewer is checking whether you can write requirements that a test could fail. "Redirects should be fast" can't fail anything. "Redirects return in under 50 ms at the 99th percentile, measured server-side" can, and someone can be paged when it does.
Section 1 left us with one insight to build on: this is two systems wearing one name. One is a thin write path used by creators like Maya. The other is a massive read path used by everyone who clicks https://tiny.example/aZ3kP9q. They get separate contracts.
The Functional Contract
Four operations, each there for a reason:
- Create a short link. An authenticated creator submits a long URL, optionally with an
expires_at, and gets back a 7-character code. Maya's 110-character campaign URL becomeshttps://tiny.example/aZ3kP9q. - Redirect. Anyone, with no sign-in, who opens the short URL is sent to the long URL. This is the product. Everything else is administration.
- Disable (delete) by owner. The creator can turn a link off. After that it stops redirecting, and its code is never reused. If an old printed QR code started pointing somewhere new, that would break trust.
- List my links. A creator pages through the links they own. Rare, but needed to manage anything.
Things we're leaving out today, each with a reason:
| Deferred feature | Why it waits | Reopened in |
|---|---|---|
Custom aliases (tiny.example/fall-sale) |
Needs a uniqueness race and a namespace that can't collide with generated codes, which is a design of its own | Section 11 |
| Analytics dashboards | Must stay off the redirect hot path. We'll keep the 302 so clicks are observable, but the pipeline comes later | Section 11 |
| Editing a link's destination | Makes link rows mutable, which complicates caching and cross-region replication | Section 11 |
| Bulk import | Only a batch wrapper around create, so it adds no new design problem | Section 11 |
Key Insight: Saying out loud what you're excluding, and why, scores as well as building it would. "Not today, because editing breaks immutability, and immutability is what makes the cache easy" tells the interviewer you already see Section 7 coming.
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