Requirements
Functional Requirements:
- Create a short URL for a given long URL.
- Return the long URL associated with a given short URL.
Non-Functional Requirements:
- read heavy workload -> redirect opration vastlly outnumber read operation so read opration should be heavily optimized
- HIgh availablity over strong consistancy
API Design
POST /api/v1/shorten
req.body : {long_url : "https://www.example.com" , custom_alies: "my_link", "ttl_days": 30
reponse 201 : {short_url: https:www.sho.rt/abc123 , "short_code" : "abc123"
GET /{short_code}
response 302: location : long_url
High-Level Design
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
Detailed Component Design
1. URL generation service (most interesting piece)
The core problem: generate a short code that is unique, short, and hard to enumerate.
Base62 encoding of a distributed ID. The most common approach: generate a globally unique 64-bit integer (via Snowflake IDs or a pre-allocated ID counter), then Base62-encode it ([a-z A-Z 0-9]). A 7-character Base62 string covers 62⁷ ≈ 3.5 trillion combinations — enough for any realistic scale.
To avoid contention at the ID generation layer, use a pre-generated pool: a background job fills a Redis list with ready-to-use codes. The Write API pops one atomically, stores the mapping, and responds. This decouples ID generation latency from write latency.
Custom aliases (user-supplied) are accepted as-is — just check for collision against the DB before confirming.
2. Redis cache (critical for the read path)
Since redirects dominate traffic and the URL mapping is immutable once written, caching is nearly perfect here. The cache key is short_code, the value is long_url. A TTL matching the link's expiry is set on write.