Web Development Project
URL Shortener
A URL shortener looks trivial and is not: you have to choose an encoding scheme, make redirects fast, stop people shortening malicious links, and handle far more reads than writes. That read-heavy asymmetry is why it is one of the most common system-design interview questions.
The brief
Accept a long URL, return a short one, and redirect on request. Track clicks, rate-limit creation, and make the redirect path fast — it will be hit far more often than anything else.
What it demonstrates
That you can reason about read-versus-write asymmetry, caching and abuse — the vocabulary of system design, demonstrated rather than recited.
What "done" looks like
Build all of these and the project is finished. Anything past that is in the stretch goals.
- Submit a long URL and receive a short one
- Redirect on visit, fast
- Click counts per link, with referrer and timestamp
- Rate limiting on creation
- Optional custom aliases with collision handling
- Rejection of malformed and dangerous URLs
How to build it
- 1
Design the schema
Links and click events as separate tables. Writing a click row per visit keeps the redirect path a single fast read.
- 2
Choose an encoding
Base62 over an auto-increment ID, or random codes with a uniqueness retry. Decide whether codes should be guessable.
- 3
Validate the input URL
Require http or https, reject javascript: and data:, and cap the length. An open redirector is abused within days.
- 4
Build the redirect
Use 302 if you want to count clicks — a 301 is cached by the browser and later visits never reach you.
- 5
Record clicks off the hot path
Redirect first, then write the analytics row asynchronously. The user should never wait on your logging.
- 6
Cache the lookup
Redis in front of the database. Reads dwarf writes here, which is the whole design lesson of this project.
- 7
Rate limit creation
Per IP or per API key, with a clear 429 and a Retry-After header rather than a silent failure.
- 8
Deploy and measure
Put it behind a real domain and check redirect latency. Sub-50ms is achievable and worth stating in the README.
Once it works
Only after the definition of done is met. Half-finished ambition reads worse than a small finished thing.
- Add QR codes for each short link
- Add expiring links and password-protected links
- Shard the code space and write up how you would scale it
Frequently Asked Questions
How should I generate the short code?
Base62-encode an auto-incrementing ID for guaranteed uniqueness with no collision check, or generate a random code and retry on conflict. Sequential codes are enumerable, so if privacy matters, use random ones or hash the ID.
Which redirect status code?
302 if you want to count clicks, because a 301 is cached permanently by the browser and later visits never reach your server. Use 301 only if you have decided analytics do not matter — this is the single most common bug in this project.
What stops abuse?
Rate-limit creation per IP or per key, check submitted URLs against a safe-browsing list, and never blindly redirect to javascript: or data: schemes. An open redirector gets used for phishing within days of being public.