Design a URL shortening service like bit.ly. Users submit a long URL and receive a short alias (e.g., short.ly/xK9p2). Clicking the short URL redirects to the original.
Write throughput: 100M URLs/day ≈ 1,160 writes/sec
Read throughput: 10B redirects/day ≈ 116,000 reads/sec → read:write ratio ~100:1
Storage: Average URL = 500 bytes. 100M × 365 × 5 years × 500 bytes ≈ 90 TB over 5 years
Short code length: Base62 with 7 chars → 62^7 ≈ 3.5 trillion unique codes. Enough for centuries.
Client
│
▼
Load Balancer
│
├── Write Service → generates short code → writes to DB + cache
└── Read Service → looks up short code → 301 redirect
│
[Redis Cache] → [Cassandra / DynamoDB]
Key insight: reads vastly outnumber writes. Optimise the read path with an in-memory cache (Redis). The cache is populated on first read and expires with the URL's TTL.
POST /api/v1/shorten
Body: { longUrl, customAlias?, ttlDays? }
Response: { shortUrl, expiresAt }
GET /{shortCode}
Response: 301 Redirect to longUrl
404 if not found or expired
url_mappings
shortCode VARCHAR(8) PK
longUrl TEXT NOT NULL
userId VARCHAR(36) nullable
createdAt TIMESTAMP
expiresAt TIMESTAMP nullable (null = never expires)
Why Cassandra / DynamoDB? The access pattern is key-value: lookup by shortCode. Wide-column stores are optimised for this and scale horizontally. PostgreSQL works fine at smaller scale.
shortCode hash for even distribution