hardSenior Backend EngineerSaaS
How would you design a URL shortener service that handles 100M+ URLs with sub-100ms redirect latency?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
This is a system design question asked during a senior backend engineer interview.
Requirements:
Write a new URL → get a short URL (e.g., Read a short URL → redirect to the original URL 100M+ URLs stored Sub-100ms redirect latency (99th percentile) High availability (99.9% uptime) Follow-up questions the interviewer asked:
1. How would you generate the short URL key?
2. How would you handle the read-heavy traffic (1000:1 read-to-write ratio)?
3. How would you scale when a single URL goes viral (millions of hits in minutes)?
4. What database would you choose and why?
Requirements:
short.url/abc123)1. How would you generate the short URL key?
2. How would you handle the read-heavy traffic (1000:1 read-to-write ratio)?
3. How would you scale when a single URL goes viral (millions of hits in minutes)?
4. What database would you choose and why?
Suggested Solution
High-Level Architecture
Client → Load Balancer → API Servers → Cache (Redis) → Database
↓
CDN (for analytics)
---1. URL Key Generation
Option A: Base62 Encoding of Auto-Increment ID
ID: 1 → Key: "1"
ID: 1000000 → Key: "4c92"
ID: 3521614606208 → Key: "zzzzzzzz" (8 chars = 218 trillion keys)
Pros: Simple, guaranteed unique, sortableCons: Predictable (competitor can estimate total URLs)
Option B: Pre-generated Key Pool (Recommended)
Key Generation Service (KGS)
Pre-generates millions of keys, stores in two tables:
- availablekeys
- usedkeys
CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
KEYLENGTH = 7 # 62^7 = 3.5 trillion unique keys
KGS runs as a separate service, hands out key ranges to API servers. Each API server gets a batch of 10K keys and uses them locally. No coordination needed.Why this is better:
2. Database Selection
Write Path (creating short URLs)
MongoDB or PostgreSQL with sharding:-- PostgreSQL schema
CREATE TABLE urls (
id BIGSERIAL,
shortkey VARCHAR(7) UNIQUE,
originalurl TEXT NOT NULL,
createdat TIMESTAMP DEFAULT NOW(),
expiresat TIMESTAMP,
clickcount BIGINT DEFAULT 0
);
CREATE INDEX idxshortkey ON urls(shortkey);
Read Path (redirecting)
Redis as the primary read store. Every redirect hits Redis first.Redis: shortkey → originalurl
TTL: 24 hours (or URL's expiry time)
---3. Handling Read-Heavy Traffic (1000:1 ratio)
Layer 1: Client-side caching
Cache-Control: public, max-age=300
Location: https://original-url.com
Layer 2: CDN edge caching
Layer 3: Redis cluster
GET abc123 → https://original-url.com in <1msLayer 4: Database (only for cache misses)
4. Viral URL Handling
When a URL "goes viral" (millions of hits/min):Thundering Herd Problem
If 10K requests hit simultaneously and the key is expired from cache, all 10K would try to fetch from DB.Solution: Cache Warmup + Request Coalescing
// Using singleflight pattern
const inflightRequests = new Map();
async function getUrl(key: string): Promise<string> {
// Check cache first
const cached = await redis.get(key);
if (cached) return cached;
// If another request is already fetching this key, wait for it
if (inflightRequests.has(key)) {
return inflightRequests.get(key);
}
// This request fetches from DB
const promise = db.query('SELECT originalurl FROM urls WHERE shortkey = $1', [key])
.then(result => {
redis.setex(key, 86400, result.originalurl);
inflightRequests.delete(key);
return result.originalurl;
});
inflightRequests.set(key, promise);
return promise;
}
Rate Limiting
5. Data Modeling for Scale
Sharding Strategy
Shard = hash(shortkey) % numshards
Each shard is independent — can be on different servers/regions.Hot Partition Mitigation
If one shard gets too hot (viral URL), use consistent hashing to redistribute.---
6. Capacity Estimation
At this scale, one Redis node + one DB primary + 2 replicas handles everything comfortably.
---