My Solution for Designing a Simple URL Shortening Service: A TinyURL Approach with Score: 8/10
by voyager_nebulous785
System requirements
Functional:
• Accept long URLs and return shortened URLs
• Redirect users from short URLs to original URLs
• Handle custom aliases (e.g., /my-link)
• Track number of visits (analytics, optional)
• Support expiration date for links (optional)
• Prevent spam or blacklisted URLs
Non-Functional:
• High availability (99.9% uptime)
• Low latency for redirects (<50ms ideally)
• Scalable to billions of URLs
• Secure (avoid malicious redirects, sanitize input)
• Consistent hash or alias generation
Capacity estimation
Assume:
• 1 billion short URLs total
• 100 million active users per month
• Each short URL is around 7 characters
Estimates:
• Storage per URL (original + metadata) ~500 bytes
• 1 billion × 500B ≈ 500 GB of storage
• Read-heavy workload: 90% redirects, 10% new URL creation
• Peak RPS (requests per second): ~100k
API design
POST /shorten
Body:
{
"original_url": "https://example.com/page",
"custom_alias": "my-link", // optional
"expires_in_days": 30 // optional
}
Response:
{
"short_url": "https://sho.rt/my-link"
}
GET /{alias}
→ Redirects to original_url (HTTP 302)
GET /analytics/{alias}
Response:
{
"clicks": 1534,
"created_at": "...",
"last_visited": "..."
}
Database design
Table: urls
Field Name Type Description
id UUID / INT Unique ID (auto-generated primary key)
short_code VARCHAR(10) Unique short string (e.g., "abc123")
original_url TEXT Full original URL
created_at TIMESTAMP When the short URL was created
expiry_date TIMESTAMP Optional, used for setting expiry on links
clicks INTEGER How many times the short URL was used
Index: short_code should be indexed for fast lookup.
High-level design
Components:
Client (UI or API consumer)
Web Server / API Layer (Node.js, Python, etc.)
Database (PostgreSQL, MongoDB, Redis for cache)
Short Code Generator
Cache (optional, e.g., Redis)
Analytics Logger (optional)
How It Works:
POST /shorten
User sends a long URL.
System checks for valid URL.
A unique short code is generated (random string or via hashing + base62).
It stores this mapping in the database.
Returns the short URL: https://short.ly/abc123
GET /:short_code
System receives the short code from the path.
It checks cache (optional) or DB for the original URL.
Logs the access (for analytics).
Redirects to the long/original URL.
Request flows
1. Shortening a URL
Client → Server (POST /shorten)
→ Validate + generate short code
→ Save to Database
→ Return shortened URL to client
2. Expanding a Short URL
Client (GET /abc123)
→ Server → Look up `abc123` in cache → if not found, check DB
→ If found, redirect to original URL
→ Optionally update click count
Detailed component design
API Gateway / Web Server
1. Handles incoming HTTP requests (/shorten, /:code)
Framework: Express (Node.js) / Flask (Python) / FastAPI
Responsibilities:
Validate user input
Communicate with service layer
Handle responses and redirections
2. URL Shortener Service (Core Logic)
Generate Short Code
Methods:
Random string (Base62 of 6-10 chars)
Hashing (md5/sha256(longURL) + truncate)
Incremental ID → Base62
Ensure uniqueness (check collision in DB)
Store Mapping
Write short_code + original_url to DB
Handle Redirects
Look up short_code
Return original URL
Optionally increment click count
3. Database Layer
SQL DB (PostgreSQL / MySQL) or NoSQL (MongoDB)
Schema as described earlier
Indexes on short_code
4. Cache (Optional but recommended)
Redis to store frequently accessed short_code → long_url pairs
Fast lookup to reduce DB hits
5. Analytics & Logging
Optional background service
Logs every access (IP, timestamp, user agent)
Stores click count in DB or analytics engine
Trade offs/Tech choices
Decision Area Option A Option B Chosen Why
Short Code Generation Random string Base62(ID) Random + uniqueness check Simple, less predictable
Storage SQL NoSQL SQL (PostgreSQL) ACID compliance, structured
Caching Redis Memcached Redis Key expiration, persistence
Hosting Monolith Microservices Monolith (initially) Easier to deploy & test
Code Lookup Cache + DB fallback DB only Cache-first Faster response
Failure scenarios/bottlenecks
Scenario Impact Mitigation
Database failure Cannot shorten or redirect DB replication, failover
Cache miss or crash Slower redirects Fallback to DB, lazy cache reload
Code collision Existing short_code gets overwritten Ensure uniqueness check before save
Bot abuse (mass URL shortening) Service degraded Rate limiting, CAPTCHA
Hot short URL (millions of redirects) DB overload Use Redis/LRU caching, CDN edge cache
Server crash Downtime Container orchestration (Docker + Kubernetes), load balancer
Future improvements
Custom Alias Support
Allow users to create /customName short URLs.
User Authentication & Dashboards
Logged-in users can manage their short links, track clicks.
Expiration & One-time URLs
Auto-expiring links or links that can only be used once.
Preview Page for Safety
Like bit.ly/preview?url=abc to prevent malicious redirection.
Analytics Dashboard
Visual charts of click trends, geolocation, devices.
Multi-region DB + CDN
For global access and low latency.
QR Code Generator
Generate QR code per short URL.
A/B Testing Framework
Randomized redirect destinations to test landing pages.