Part V — Casebook: Real Interview Problems, Solved
Every case follows the same template as §2: business context → requirements → estimates → API & data → design → deep dives → failure modes → strategic lens → follow-ups, followed by a 🏗️ flow diagram, 🌍 how it's built in production (from real engineering blogs and papers), and ⚠️ corner cases. The strategic lens (business, cost, org, evolution) is expected at Staff level and above and from managers; at Senior level it's what lifts a solid answer to a strong one. The cases get harder roughly in order. Practice them out loud against a 45-minute timer, drawing as you go (§63), before reading the solutions.
31. URL Shortener (warm-up)
Business context. A marketing-links product (like bit.ly). Revenue comes from click analytics for paying customers. Redirect latency and availability are the product. A broken link in a printed ad can't be fixed.
Requirements. Create a short URL (optional custom alias, expiry); redirect; click analytics. NFRs: 100M new URLs/month; 10B redirects/month; redirect p99 < 50 ms at the edge; 99.99% redirect availability; links never collide or change.
Estimates.
Writes: 100M / 2.6M s ≈ 40/s (peak ~200/s) → trivial
Reads: 10B / 2.6M s ≈ 4,000/s (peak ~20k/s, viral spikes 100k+/s on one key)
Storage: 100M * 12 months * 5 yrs * ~500 B ≈ 3 TB → fits easily in a KV store
Key space: base62, 7 chars → 62^7 ≈ 3.5 trillion → enough for decades
API.
POST /v1/links {long_url, custom_alias?, expires_at?} → {short_code}
GET /{short_code} → 301/302 Location: long_url
GET /v1/links/{code}/stats?from&to
Generating codes: the core decision.
| Approach | Pros | Cons |
|---|---|---|
| Hash(long_url) and take 7 chars | Deterministic, same URL → same code | Collisions need a check-and-retry loop; per-customer links need a salt |
| Counter + base62 (range allocation: each server leases a block of 1M IDs from a coordinator) | No collisions, no coordination per request | Sequential codes are enumerable → mix the bits with a reversible permutation if that matters |
| Random 7 chars + uniqueness check | Simple, non-guessable | Extra read per write (fine at 40/s) |
| Pre-generated key service | Fast handout | Another service to run |
Design.
Create: client → API → ID-range allocator (lease blocks) → base62 → KV store (code → url, owner, expiry)
Redirect: client → CDN/edge (cache 301s for popular codes) → redirect service → cache (Redis) → KV store
└── emit click event (async, fire-and-forget to a local buffer → Kafka) → analytics pipeline
Deep dives.
- 301 vs 302: 301 is cached by browsers (cheaper, but you lose analytics on repeat clicks); 302 records every click. The business need (paid analytics) means 302, plus edge caching at the CDN for a few seconds to absorb viral spikes.
- The analytics write path must never slow the redirect. Buffer locally and drop on overload. Losing 0.01% of click events is acceptable; a slow redirect isn't.
- Abuse: phishing and malware links hurt domain reputation. Run safe-browsing checks on creation, and rescan asynchronously.
Strategic lens. The real risk to the business isn't scale. It's domain reputation (spam filters blocking the short domain) and link permanence. Multi-region read replicas for redirects and a DR-tested KV store matter more than clever ID schemes.
Follow-ups: custom domains per customer (TLS certificates at scale, e.g. ACME automation); GDPR deletion of click data; how to expire links (a TTL in the KV store plus lazy checks).
🏗️ Flow: redirect hot path with an analytics side channel.
Browser ─GET /aZ3kQ9x─▶ Edge PoP
├─ edge KV / cache hit (popular code, TTL 60 s) ──▶ 302 Location: … (≈10 ms)
└─ miss ─▶ Redirect svc ─▶ Redis (code→url) ─miss─▶ KV store (DynamoDB/Bigtable)
│ (replicated, multi-region)
└─ enqueue click {code, ts, ip-hash, ua, referrer}
to in-memory ring buffer → batch → Kafka (drop if full)
Kafka ─▶ stream job (bot filter, dedupe) ─▶ OLAP (per-link per-minute counts) ─▶ customer dashboards
🌍 How it's built in production.
- Twitter's t.co wraps every link in a tweet, which lets Twitter check links for malware and phishing at click time (not only at creation) and measure engagement. It's the same pattern: a redirect service plus safety checks plus analytics.
- ID generation in the wild: Twitter's Snowflake (2010: 41 bits timestamp + 10 bits machine + 12 bits sequence) and Instagram's Postgres-generated IDs (§9.7) are the standard references for coordination-free, time-ordered IDs. Encode them in base62 for short codes.
⚠️ Corner cases.
- Reserved paths: a user registers the custom alias
api,login, oradmin, which collides with your routes. Keep a reserved-word list. - Case sensitivity and look-alikes: base62 is case-sensitive, but people retype links in lowercase from print. Offer a case-insensitive alphabet (base36) for printed codes, and avoid ambiguous characters (0/O, 1/l/I).
- Never reuse expired codes: an old printed QR code would send people to a new owner's URL (phishing). Expired codes are tombstoned forever.
- Destination edits: if customers can change the target URL, cached redirects at the edge and in browsers (if you used 301) keep the old target. Use short TTLs and purge on edit.
- Redirect loops and chains: a short link pointing at another short link, or at itself. Resolve and reject on creation.
- Bot inflation: link previewers (Slack, iMessage, social crawlers) fetch the URL and count as clicks. Classify by user agent and behavior, and report "human clicks" separately.