Requirements
Functional Requirements:
- User should get a short URL corresponding to the requested long URL
- User should be able to redirect to original URL upon hitting short URL on browser search bar
Non-Functional Requirements:
- System latency should be as low as possible like less than or equal to 200 ms
- System should be highly available and partition tolerant as consistency is already maintained. One short URL is mapped to one long URL so no duplicates exist
- Every short URL must be unique
API Design
endpoint: POST /api/v1/urls
Request Body: {
"long_url": "https://domain/endpoint",
"expires_at": expire_time
}
Response: {
"long_url": "https://domain/endpoint",
"short_url": "https://shorturl/
"expires_at": expire_time
High-Level Design
Client: Regular device - mobile, website, webapp
Load Balancers: To redirect user request to highest available server when multiple app servers are present. This helps in managing large traffic
Application Servers: For generating and mapping a short URL corresponding to a long URL, storing the mapping on database, returning short URL as response during creation and redirecting to original long URL when the short URL request comes
Caching layer: As read requests will be more than write requests (writes on DB are only done once during creation phase of short URL), we need to store frequently queried URLs in memory stores like redis, avoiding DB access when same request comes again. This is necessary because database operations are heavy and we should avoid latency where ever possible
Database layer: Contains mapping of short URL to long URL along with user_id, expiry time, time of creation etc. Will have short_url column as primary key to ensure unique short URLs for each long URL. Anytime a read operation happens store the result in cache to avoid re querying DB for same URL
Detailed Component Design
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.