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:


  • low latency fetch of long url p95 10 ms
  • low latency creation of short url p95

100 ms

  • scalable upto 1 billion overall urls
  • fault tolerant
  • analytics on urls.
  • availability over consistency


scale

200 url creations per second

20000 url reads per second

overall 1 billion urls.


API Design


post /urls

{

longurl

} -> StatusCode, shortUrl


get /orignialurl/{shorturl} -> longurl, 301 status code


High-Level Design

client will call api gateway. the creation of urls will go to create service and read calls will go to read microservice. One postgres instance will be used. It will have one table containing urls longUrl, shortUrl mapping. Shorturl will have a secondary index for easy retrieval of long urls. 20000 reads hitting a postgres might be too much. We will configure a redis cache to serve reads. Redis cache will be updated on read. Redis size for 1 billion urls will be around 20 GB which will fit in one instance. Majority of the read calls will be served by redis.

For creation, we will use base62 conversion. We will convert a number to a base 62 number. This number will be provided by redis. Everytime a creation call comes, we will go to redis, update the counter, convert it to a base62 number and then save it to database. Primary key is a combination of longurl, shortUrl in the datbase which will make sure every row is unique.


Detailed Component Design

Creation service will get a counter from redis. In redis, we will set a counter and increment it on every creation call. We will use redis INCR command for that to increment redis counter. We will convert the counter to a base62 number and then this number will be the tiny url like https://tinyurl.com/{base62number}. This will be saved in the database. Redis will have peristence configured with append only file. creation service volume is not high so we will deploy 3 role instances and one of them would be active. Read service will get autoscaled based on the requests thats are coming. 20000 read calls per second can be an issue for the postgres. So we will use redis and store the short Url to long url mapping in redis key value store. One redis instance should be able to handle 20000 read calls. 3 nodes will be deployed in the redis for failover.

There will be rate limiting at a user level to prevent abuse of the service. Also there will be rate limiting at a url level. the quota per short url to get the long url. We can use redis senitel setup for storing counter as well as short url to long url mapping.