Functional Requirement :
1) User generate short url for big url
2) User is able to redirect to the orginal link from the short url
3) User can create profile and create url associated with its profile
Non functional requirement
1) Scalable -> add more url, and server more redirect
2) Latency -> 5ms ?
3) Available -> as much as possible
4) Read Heavy
Create Short URL
Endpoint
POST /urls
Request Body
{
"longUrl": "https://example.com/very/long/url",
"expiry": "2026-06-01T00:00:00Z"
}
Response
{
"shortUrl": "https://short.ly/abc123",
"shortCode": "abc123",
"expiry": "2026-06-01T00:00:00Z"
}
2. Redirect to Original URL
Endpoint
GET /{shortCode}
Example:
GET /abc123
Behavior
- Looks up
shortCode - Fetches original URL
- Returns HTTP redirect
Response
302 Found
Location: https://example.com/very/long/url
High-Level Design
client -> gateway -> user Service -> userDb
UserDb { id , userName , name , emailId , phoneNumber }
For user data, PostgreSQL is usually better because:
- User schema is stable
- Relationships and constraints matter
- Strong consistency is important
MongoDB can be considered if:
- Schema changes frequently
- Massive horizontal scaling is required
- Product evolves rapidly
client -> gateway -> url Service -> urlDb
urlDb{ id , shortUrl , longUrl , expiry }
1. User submits long URL
2. URL Service generates short URL
3. Store mapping in PostgreSQL
4. Cache mapping in Redis with TTL
1. Client requests short URL
2. Check Redis first
3. If cache hit → return long URL
4. If cache miss:
→ query PostgreSQL
→ populate Redis
→ redirect user
Redis vs Postgresql
PostgreSQL
Used as:
- Source of truth
- Permanent storage
Redis
Used as:
- Cache layer
- Fast URL resolution
- TTL-based expiration
Detailed Component Design
Yes. Your current points are good, but some components can be clarified and strengthened. It looks like you’re designing a URL Shortener system (like TinyURL/Bitly) with focus on scalability, latency, and concurrency.
Here is an improved component design:
1. API Layer
- API Gateway / Load Balancer
- Route traffic to services
- Rate limiting
- Authentication
Client → Load Balancer → Services
2. URL Service (Stateless, EKS Managed)
Responsibilities:
- Create short URL
- Redirect short URL → original URL
- Read from Redis first
- Write metadata to DB
Improvements:
- Deploy on EKS/Kubernetes
- Horizontal Pod Autoscaler (HPA)
- Multiple replicas
URL Service Pods (EKS)
├── Pod 1
├── Pod 2
└── Pod N
3. User Service (Stateless, EKS Managed)
Responsibilities:
- User profile
- Authentication
- User URL history
Also horizontally scalable.
4. Redis Cache (Low Latency)
Purpose:
shortUrl -> originalUrl
Flow:
Read Request
↓
Redis Cache
↓ Hit
Return URL
↓ Miss
DB Lookup
↓
Populate Redis
↓
Return URL
Your question:
Concurrent request issue? Multiple reads same row supported?
Answer: Multiple reads are usually not a problem.
Redis supports very high concurrent reads (millions/sec possible depending on setup).
DB also supports concurrent reads through:
- Read replicas
- MVCC (e.g., PostgreSQL)
- Connection pooling
Issue happens more with:
- Multiple writes on same resource
- Cache stampede (many requests after cache expiry)
Example:
Redis key expires
1000 requests come simultaneously
All hit DB
DB overload
Solution:
- Redis locking
- Cache warming
- Random TTL
- Request coalescing
5. Persistent Storage (Primary DB)
Your question:
Cache miss? Persist somewhere else?
Yes.
Redis is cache, not source of truth.
Need persistent DB:
Redis (Fast cache)
↓ Miss
Aurora/Postgres/DynamoDB
Store:
ShortURL
LongURL
UserId
CreatedAt
Expiry
Can also use:
- Read replicas for scaling reads
6. URL ID Generation (Collision Avoidance)
Your point:
7 bit uuid generation unique
7 bits gives:
2^7 = 128 values
Too small.
Need something like:
Options:
Option 1: Snowflake ID
Timestamp + MachineId + Sequence
Example:
41 bits Timestamp
10 bits Machine ID
12 bits Sequence
No collision.
Option 2: Base62 Encoding + Counter
10001 → "2Bh"
Counter from distributed ID generator.
Option 3: UUIDv7 + Base62
UUIDv7 gives:
- Time sortable
- Very low collision probability
Encode to Base62 for short URL.
Example:
UUIDv7
↓
Base62
↓
"abX92P"
7. Analytics Service (Async)
Don’t update click count synchronously.
Redirect
↓
Kafka/SQS
↓
Analytics Consumer
↓
DB
Reduces latency.
8. CDN (Optional)
Popular URLs:
Edge CDN
↓
Redis
↓
DB
Reduces redirect latency globally.
Final Improved Architecture
Client
↓
Load Balancer / API Gateway
↓
--------------------------------
| URL Service (EKS, Stateless) |
| User Service (EKS) |
--------------------------------
↓
Redis Cache Cluster
↓ Miss
Primary DB (Aurora/Postgres/Dynamo)
↑
Read Replicas
URL Generation
↓
UUIDv7/Snowflake/Base62
Analytics
↓
Kafka/SQS
↓
Consumer
↓
Analytics DB
Key improvements:
- ✅ Horizontal scalability → EKS + HPA
- ✅ Low latency → Redis + async analytics
- ✅ Cache miss handling → Persistent DB
- ✅ Collision avoidance → UUIDv7/Snowflake
- ✅ Concurrent reads → Redis handles well
- ✅ DB protection → Cache stampede prevention
- ✅ Global scale → CDN + replicas
This becomes closer to a production-grade system design answer for interviews.