Requirements & API: URL Shortener

What an interviewer expects you to nail down before drawing a single box.

Functional

  • Given a long URL, return a unique short URL.
  • Given a short URL, redirect to the original long URL.
  • Optionally support custom aliases and link expiry.
  • Track click counts per short link (analytics, off the critical path).

Non-functional

  • Redirects must resolve in single-digit milliseconds (p99).
  • Read-heavy: reads outnumber writes ~100:1.
  • High availability. A dead redirect path breaks every link ever issued.
  • Short keys must be non-guessable enough to deter enumeration.

API contract

POST /api/v1/shorten { long_url, custom_alias?, expire_at? } → { short_url }
Authenticated + rate-limited. Returns 409 if a custom alias is taken.
GET /{short_key} → 301/302 redirect
The hot path. Served from cache for ~99% of traffic.
DELETE /api/v1/{short_key} → 204
Owner-only. Invalidates the cache entry.

About URL Shortener

Think about what happens when you paste a long, ugly link into a tweet. A URL shortener takes that link and hands you back something tiny like sho.rt/aB3xK9 that redirects to the original. It looks trivial, and that is exactly why interviewers like it as a warm-up. Underneath, it teaches patterns you will see in almost every system: how to generate a unique key, how to serve reads cheaply, and what to do when reads far outnumber writes.

Here is the whole thing in plain terms. When you submit a long URL, a write service creates a short key and stores the pair (short key, long URL) in a database. When someone clicks the short link, a read service looks up the key and redirects them.

The one decision worth thinking about is how you make the short key. You can keep a counter and encode it in base62, which never produces the same key twice. Or you can hash the URL, which is handy when you want the same link to always shorten to the same code, as long as you handle the rare collision.

Why does the design need a cache? A handful of links get shared everywhere while most are clicked once or twice, the same way a few songs get played millions of times while the rest sit untouched. Put those popular links in Redis and the database barely sees the redirect traffic. Reads outnumber writes by roughly 100 to 1, so almost everything here is about keeping that read path fast: a cache in front, read replicas behind, and a CDN at the edge once you go global.