Beginner System Design Interview: Design Bitly w/ a Ex-Meta Staff Engineer
Tony Duong
Jun 17, 2026 γ» 5 min

Notes from Hello Interview (Evan, ex-Meta staff engineer) on designing a URL shortener like Bitly β positioned as the classic beginner system design question, with concepts explained more slowly than in their advanced videos.
Interview roadmap
- Requirements (functional + non-functional)
- Core entities
- API
- High-level design (satisfy functional requirements)
- Deep dives (satisfy non-functional requirements)
Skip data flow for user-facing product designs (save that for infra questions like rate limiters or message queues).
Back-of-envelope math upfront is optional β only estimate when numbers change the design.
What the system does
A URL shortener converts long URLs into short ones; visiting the short URL redirects to the original.
Functional requirements
- Users can create a short URL from a long URL
- Users can be redirected to the original URL from the short URL
Common optional extensions in interviews:
- Custom alias β user provides their own short code (e.g.
bit.ly/Evan) if not taken - Expiration time β short URL valid only for a period (e.g. conference link for one week)
Non-functional requirements
Typical scale Evan gives candidates:
- 100 million DAU
- ~1 billion URLs shortened over all time
Other NFRs to call out in context:
| Concern | URL shortener framing |
|---|---|
| Low-latency redirects | Redirect path must be fast β users feel latency immediately |
| Unique short codes | Collisions redirect users to wrong sites β must guarantee uniqueness |
| Scalability | Support 100M DAU and 1B stored mappings |
| CAP | Favor availability + partition tolerance over strong consistency (see below) |
Core entities
- User β owns short URLs (email, password hash, etc. are auxiliary; don't over-detail in interviews)
- URL mapping β short code β long URL (the core table)
API
POST /urlsβ body: long URL (+ optional custom alias, optional expiration) β returns short URLGET /{shortCode}β redirect to long URL (302 in the high-level design)
High-level design (v1)
Client β Load balancer β URL Service β Database (URL mappings)
- Create: insert
(shortCode, longUrl)β return short URL - Redirect: lookup
shortCodeβ return 302 redirect to long URL
301 vs 302 redirects
| Code | Behavior | When to use |
|---|---|---|
| 302 | Temporary β browser always hits your server | Default when you don't need analytics, or want every redirect logged |
| 301 | Permanent β browsers/CDNs may cache; may skip your server | When redirects are truly permanent and you don't need per-click logging |
For Bitly without analytics, 302 is fine. With analytics, 302 ensures redirects always reach your server so you can count clicks.
Deep dive: generating short codes
Bad approaches:
- Prefix of long URL β many URLs share prefixes (
twitter.com/...) β one-to-many mapping, collisions - Hash long URL only β deterministic, so same long URL always gets same short code (OK for dedup), but hash collisions need handling; append salt/rehash on collision
Good approaches:
Counter + base62 (recommended in video)
- Maintain an auto-incrementing counter per new URL
- Base62 encode the counter (0β9, AβZ, aβz) for compact strings
- 6 characters β 62βΆ β 56 billion combinations
- No collisions β sequential IDs are unique by construction
Random number + base62
- Pick random integer in [0, 56B), base62 encode
- Birthday paradox: collision probability rises faster than intuition β with ~1B URLs, collisions become a real concern
- Must check DB and retry on collision
Hash long URL + base62 slice
- Hash (MD5, Murmur, SHA-256) β base62 β take first 6 chars
- Deterministic dedup for same long URL
- On collision, append salt and rehash
Deep dive: CAP and consistency
URL shortener does not need strong read-after-write consistency (unlike banking or ticket booking).
If a user creates a short URL and shares it instantly, eventual consistency is acceptable β a brief "try again in a minute" error is tolerable. Favor AP over CP.
Deep dive: scaling reads (redirect-heavy)
Redirects dominate traffic β read-heavy workload.
Read/write service split
- Write service β creates short URLs
- Read service β handles redirects
- API Gateway routes
POST /urlsβ write service,GET /{shortCode}β read service
Scale each tier horizontally (auto-scaling groups behind load balancer).
Redis cache (read-through LRU)
- On redirect: check Redis for
shortCode β longUrl - Cache miss: read DB, populate cache, return
- Read-through + LRU eviction for hot short URLs
Primary key lookup on Postgres (B-tree) is already fast, but cache removes DB load at scale.
Peak redirect QPS (rough): 100M DAU Γ a few redirects/day β ~1K req/s average, 10β100K req/s at peak with burst multiplier.
Key Takeaways
- Bitly is the classic entry-level system design question β requirements β entities β API β design β deep dives
- Counter + base62 is the cleanest collision-free short-code strategy; random needs birthday-paradox math
- Never use URL prefix as short code β shared prefixes break one-to-one mapping
- 302 vs 301 depends on whether you need server-side redirect logging (analytics)
- Read/write split + Redis read-through cache for redirect-heavy scaling
- Eventual consistency is OK β not every system needs strong read-after-write
- Only run back-of-envelope estimates when they change architectural decisions