TinyURL is often called the “Hello World” of system design because it has minimal requirements but forces us to think about scalability, caching, ID generation, and bottlenecks.
Let’s design it step by step.
Functional Requirements :
- Convert a Long URL → Short URL
- Redirect Short URL → Long URL
Non-Functional Requirements:
- High Availability
- Low Latency
- Scalable under heavy traffic
API End-Points:
- POST /shorten → Accepts Long URL
- GET /{shortId} → Redirects to Long URL
High-Level Design:

This is a simple and scalable design.
Since we require low latency, we introduce a cache layer to store frequently accessed short URLs. Most read requests will be served directly from cache, reducing database load.
To ensure high availability, we avoid single points of failure. App servers are scaled horizontally and placed behind a load balancer, which distributes incoming traffic evenly.
Because our system only needs to store simple mappings:
short_url → long_url
we can use either:
- A Key-Value database (natural fit for simple mapping)
- Or an SQL database if additional analytics or constraints are required
This covers the basic design derived from requirements.
But now comes the interesting part.
How Short Should the URL Be?
We want to convert long URLs into short ones. But how short should they be?
Assume:
K new URLs are generated every second.
We store URLs for 10 years.
Total URLs required:
K*60*60*24*365*10
If our short URL can use:
- 26 lowercase letters (a–z)
- 26 uppercase letters (A–Z)
- 10 digits (0–9)
That gives us 62 possible characters.
To determine required length:
62^n ≥ K × 60 × 60 × 24 × 365 × 10
Where n is the length of the short URL.
If n = 7:
62^7 ≈ 3.5 trillion combinations
Which is sufficient for large-scale systems.
Bottlenecks
Hot Key Problem (Read Bottleneck)
Suppose the application becomes popular and millions of users request the same short URL simultaneously.
Where would the system collapse first?
The cache.
When many users access the same key, we face a hot key problem. Horizontal scaling alone does not solve this because the same key may map to the same cache node.
Solution:
- Use cache replicas
- Introduce a CDN layer Distribute read load across multiple cache nodes
Write Bottleneck (Database)
Now assume we receive a large number of write requests (URL creation) and writes typically go to the primary database node.
Where will the bottleneck occur?
The database.
Since every new short URL requires a write operation, database throughput becomes the limiting factor.
Solution:
Sharding the database.
However, simple modulo-based sharding can cause problems when adding new shards because it requires massive data redistribution.
A better approach is:
Consistent hashing, which minimizes data movement when scaling.
ID Collision Problem
Since app servers are horizontally scaled, two servers might generate the same short URL.
How do we prevent collisions?
Possible approaches:
- Random Base62 generation + collision check
- Centralized ID generator
- Distributed ID service
- Using Redis atomic counter (e.g., INCR)
Final Thought
TinyURL may look simple, but it teaches us:
- Scalability
- Caching strategies
- Sharding techniques
- Bottleneck analysis
- ID generation trade-offs
That’s why it’s called the “Hello World” of System Design. Let's meet again with another interesting design.
Top comments (0)