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:
- latency
- high availability (99.99%)
- scalability
API Design
Post /shorten
Body: {long_url}
Response: {short_url}
Get /url/{short_url}
Response: 301/302 for redirect
High-Level Design
Architecture:
- Service-oriented with independently scaling services
- stateless services
- all services emit telemetry
Entity Data Models:
ShortUrl:
id (pk)
short_url (unique, indexed)
long_url
created_at
updated_at
Detailed Component Design
Redirect service
- check if the short url is cached, if not uses db as fallback
- once it finds a short url match it redirects the user to the long url
Shortening Service
- check if long url already exist in db, if it does it returns the short_url for it
- if it's a new long_url, it base encodes the url into a short version
- stores the short url into the db
- adds the short url to cache, to get it ready for use
- returns the generated short url back to the user
DB
- uses synchronous replicas for strong consistency & fault tolerance
- primary db for writes, reads from replicas
- For horizontal scaling, the db can be sharded using the short url id as the hash key, and consistent hashing. This way the number of shards can be increased or decreased with minimal remapping required.