Designing a URL Shortener (like Bit.ly) requires considerations for scalability, performance, and reliability. Let's break it down step by step.
* Shorten a long URL and generate a unique short URL
* Redirect users when they visit the short URL
* Track analytics (clicks, location, browser, etc.)
* Support custom short URLs
* High availability and low latency
* Scalability to handle millions of requests
* Security to prevent abuse (e.g., spamming, phishing)
Endpoint | Functionality |
---|---|
POST /shorten |
Takes a long URL and returns a short URL |
GET /{shortUrl} |
Redirects to the original URL |
GET /stats/{shortUrl} |
Retrieves analytics for the short URL |
Two main options :
A simple SQL table might look like:
short_id (PK) | long_url | created_at | expiration_date | click_count |
---|---|---|---|---|
abc123 | https://example.com/some-long-url | 2025-02-06 | NULL | 1200 |
Indexes should be added on short_id
for fast lookups.
abc123
)import string
CHARACTERS = string.ascii_letters + string.digits # a-z, A-Z, 0-9
BASE = len(CHARACTERS)
def encode(num):
"""Encodes a number to Base62."""
short_url = []
while num > 0:
short_url.append(CHARACTERS[num % BASE])
num //= BASE
return ''.join(reversed(short_url))
This approach avoids collisions and allows incremental IDs.
When a user visits a short URL:
short_id
from the request.long_url
.long_url
.Example Nginx configuration:
location /s/ {
rewrite ^/s/(.*)$ /redirect.php?short_id=$1 last;
}
Component | Technology |
---|---|
Backend | Python (Flask, FastAPI) / Node.js (Express) |
Database | PostgreSQL / DynamoDB / Redis |
Caching | Redis / Memcached |
Load Balancer | Nginx / AWS ALB |
Message Queue | Kafka / RabbitMQ |
CDN | Cloudflare / AWS CloudFront |