AiTechWorlds
AiTechWorlds
It is 2008. bit.ly launches as a service for shortening long URLs to compact links. By 2023, bit.ly is handling over 2 billion monthly requests — billions of clicks redirecting users from short links to their destinations. The average click must complete in under 100 milliseconds. The service must never go down.
"Design a URL shortener" is the most common system design interview question at Google, Amazon, Meta, and Uber — not because URL shorteners are particularly important, but because designing one correctly requires you to apply every concept in system design: scale estimation, database choice, caching, load balancing, distributed ID generation, and deployment strategy.
This lesson is a complete walkthrough. By the end, you will have designed a production-grade URL shortener and synthesised everything from all 18 lessons in this course.
Before designing anything, clarify requirements. A system design session without requirements is an architect without blueprints.
The features the system must provide:
bit.ly/abc123).bit.ly/my-product).The quality attributes the system must meet:
Back-of-the-envelope calculations reveal the true design challenges before you commit to an architecture.
Key insight from the math: The 1,000:1 read-to-write ratio means the design must optimise aggressively for reads. Caching is not optional — it is the core architectural decision.
Component roles:
A 6-character base62 code (characters a–z, A–Z, 0–9) provides 62^6 = 56.8 billion unique codes — enough for the 18.25 billion URLs over 5 years.
Option A — Hash + truncate: Take a hash of the long URL (MD5, SHA-256), take the first 6 characters. Simple, but:
Option B — Auto-increment ID + base62 encoding:
Use a database auto-increment ID (1, 2, 3...). Convert to base62. ID 1 = "1", ID 62 = "10", ID 3844 = "100". Guaranteed unique, sequential, no collisions.
Option C — Key Generation Service (chosen): Pre-generate 100 million unique 6-character codes and store them in a Redis set. API servers atomically pop keys from the pool on demand. This removes ID generation from the write path entirely — a key is available instantly. Background jobs replenish the pool when it drops below a threshold.
Why KGS wins: No database write is needed during the short code assignment. No collision handling. Ultra-low latency key issuance (Redis SPOP is O(1)).
CREATE TABLE url_mappings (
short_code CHAR(8) PRIMARY KEY,
long_url TEXT NOT NULL,
user_id BIGINT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ,
is_active BOOLEAN NOT NULL DEFAULT TRUE
);
CREATE INDEX idx_short_code ON url_mappings (short_code);
CREATE INDEX idx_user_id ON url_mappings (user_id);
Cache-aside with Redis. On redirect:
short_code → long_url. (~0.5ms)Target: 90% cache hit rate. With 115,000 redirects/second and 90% hit rate, only 11,500 requests/second hit PostgreSQL — well within the capacity of read replicas.
Cache sizing: Popular links need only 500 bytes per entry. 1 million cached entries = 500 MB. A standard Redis instance handles this easily. The 80/20 rule applies: 20% of URLs receive 80% of traffic. Cache the hot 20%.
When a user clicks a short link, the server responds with either a 301 or 302 HTTP status code.
| HTTP 301 (Permanent) | HTTP 302 (Temporary) | |
|---|---|---|
| Browser behaviour | Caches the redirect — never asks our server again | Asks our server on every click |
| Analytics | No click data after first visit | Full click data on every visit |
| Server load | Lower (browsers cache) | Higher (every click hits us) |
| Chosen for | Public bit.ly-style sharing | Analytics-critical dashboards |
Decision: Use HTTP 302. The primary value proposition of a URL shortener service is analytics. Without click data, the product has limited value. The trade-off: higher server load, which we handle with caching.
Without rate limiting, a single bad actor could generate millions of short URLs per minute, consuming the key pool and filling the database with spam.
Rate limiting strategy: Token bucket per API key / IP address.
Implementation: Redis with a sliding window counter. INCR and EXPIRE operations atomically enforce the limit with O(1) complexity.
| Decision | Option A | Option B | Chosen | Reason |
|---|---|---|---|---|
| Short code generation | Hash + truncate | Auto-increment + base62 | Key Generation Service | No collisions, no DB write on hot path |
| Primary database | MySQL | PostgreSQL | PostgreSQL | Better JSON support, strong community, JSONB for metadata |
| Analytics storage | PostgreSQL | Cassandra | Cassandra | Write-optimised for billions of click events |
| Cache strategy | Write-through | Cache-aside | Cache-aside | Only cache what is accessed; graceful fallback |
| Redirect type | 301 Permanent | 302 Temporary | 302 | Enables per-click analytics |
| API style | REST | GraphQL | REST | Simple CRUD operations; no over-fetching problem |
| Deployment | Blue-Green | Canary | Canary | Gradual confidence with 10B daily redirects |
| Message queue | RabbitMQ | Kafka | Kafka | Replay capability for analytics backfill; throughput |
Designing a URL shortener is a lens through which every system design concept becomes concrete.
| Lesson | Applied In This Design |
|---|---|
| Caching Strategies | Redis cache-aside for URL mappings, 90% hit rate target |
| Databases | PostgreSQL for mappings, Cassandra for analytics — right tool for each workload |
| Microservices | Separate Key Generation Service, Analytics Service, API Service |
| API Design | REST endpoints for URL CRUD, HTTP status codes 301/302 |
| Message Queues | Kafka for click event streaming to analytics pipeline |
| Software Testing | Unit tests for base62 encoding, integration tests for redirect flow |
| Security | Rate limiting, URL validation (block malicious links), HTTPS everywhere |
| DevOps / CI/CD | Docker containers, Kubernetes for API servers, canary deployments |
The URL shortener handles 10 billion redirects per day. But the same patterns — scale estimation, cache-first reads, async event processing, stateless API servers behind a load balancer — underpin every large-scale system you will ever build: social media feeds, e-commerce platforms, financial systems, and streaming services.
System design is not a collection of tricks. It is a way of thinking: clarify requirements, estimate scale, identify bottlenecks, choose trade-offs deliberately. You have now practised that way of thinking across 18 lessons and one complete design. The next step is applying it to something you are building yourself.
Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises