URL:- POST /shorten
Request:- {
"long_url": "https://example.com/abc",
"custom_alias": "myurl", // optional
"expiry": "2026-12-31" // optional
}
Response:-
{
"short_url" : "https://tinyurl.com/abc123"
}
URL: -GET /{short_code}
Response:- HTTP 301 Redirect -> Original URL
URL:- GET /analytics/{short_code}
Client -> Load Balancer -> API Servers -> Cache -> Database
Load Balancer
API Servers (Node.js)
Cache (Redis)
Database (MYSQL/NOSQL)
Redirect Flow
System is read-heavy. Cache is critical.
URL Generation
Approach - Auto Increment ID -> Base62 encoding
Example - ID = 125 -> "cb"
Problem: Predictable IDs
Sequencial IDs can be guessed.
Solution:
short_code = Base62(ID XOR random_salt)
Prevents enumeration attacks
Scalable Option:
Use Distributed ID Generator
timestamp + machine_id + sequence
Avoids bottleneck of single DB
CONCURRENT CREATES & COLLISION
Auto Increment ensures uniqueness
DB Gurantees atomic inserts
If using random codes
Problem: Collision Possible
Solution: UNIQUE Constraint + retry
REDIRECT Service
Flow:
Check Redis
If hit -> return
If miss -> Db lookup
Cache result
Return 301 Redirect
Why 301?
Cache Design (Redis)
Strategy - Cache Aside
Key Design
Key = url:{short_code}
value = long_url
Why Cache
Failure Handling
If Redis Fails
Fallback -> DB
Production Setup
DataBase Design (MYSQL)
Schema
CREATE TABLE urls (
id BIGINT PRIMARY KEY,
short_code VARCHAR(10) UNIQUE,
long_url TEXT,
created_at TIMESTAMP,
expiry TIMESTAMP
);
Optimization
SCALABILITY
API Layer
Stateless -> Horizontal Scaling
Database
Cache
Fault Tolerance
Redis Failure
Generator Failure
Split Brain Handling
use machine_id in ID Generation
Traffic Spikes
System should:
Analytics (ASYNC)
Do Not Update DB Per request
Solution
Flow
Redirect -> publish event -> process async -> batch update DB
Expiry & Data Management
Expiry Strategy
Scaling Data