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:
- Availability
- Low Latency
API Design
There are 2 endpoints exposed to the system
POST /register -> Expects a string url and return either error or a string (shortened url). Checks if the same base url exists, if yes returns the existing mapping else maps the url with the next available url and stores that in db and set redis key and returns the same.
GET /url -> returns mapped url if exists else error.
High-Level Design
We just need 3 layers
- A light weight service, where the business logic resides.
- A database, postgres. Since request response is defined.
- A redis cache layer for storing the url mapping.
Detailed Component Design
Database comprises of 3 tables: users, access_tokens, url_mapping
- Users: first_name string, last_name string, email string, password string, id int, created_at TIMESTAMP, updated_at TIMESTAMP, deleted_at TIMESTAMP.
- access_tokens: id int, user_id int, token string, created_at TIMESTAMP, deleted_at TIMESTAMP
- url_mapping: id int, url string, shortened_url string, created_at TIMESTAMP, deleted_at TIMESTAMP, mapped_by int.
Redis will only store key values : url -> short_url with LFU eviction strategy.
The service layer logic is very simple. For GET request it checks if the url exists in cache, if found return the corresponding short url. If cache miss, we fetch db, set cache if found, return the shortened url. If not, we return 404 NOT Found and a user friendly message.
The POST endpoint expects a string url: checks if the url is correct format, then checks the cache if the same url exists, if yes returns the already mapped shortened url, else stores in db, set in cache and returns the shortened url.
The users table is for users who wish to login.