To shorten a large url into a smaller one.
We want to optomize for latency as this service takes too long it makes it pointless.
Assuming the endpoint is hit 1 billion times a month this means roughly 33 million hits a day, which if we assume a day has roughly 100000 seconds, we are at 333 requests per second.
now it terms of database, assuming each link has a max expiration of 5 years, roughly 60 billion possibilities of urls. 12 billion a year or 60 billion every 5 years. Lets say we want to use A-Z, a-z and 0-9. so we are at 62 characters possible to use. We need roughly 6 characters to achieve this lets say 7 to be safe.
Each character takes roughly a byte but lets say we also want to store so metadata and we also have to store the long url.
so lets say 1kb per request. Which is a terabyte a month and 12 terabytes a year and 60 terabytes max storage.
Define what APIs are expected from the system...
so we need a post request to create the url, we would pass something like https://tinyurl/create_url
with params: {
expiration,
date_created,
long_url,
user_id
} returning something like { short_url, url_id, expiration }
We would also want a way to fetch your specific url or all your urls associated with your user. These would be with get requests.
https://tinyurl/users/:id/:url_id for a specific url returning something like { short_url, url_id, expiration }
or https://tinyurl/users/:id/urls which returns a list of { short_url, url_id, expiration }
Since we are optimizing for read heavy low latency operations. We are not prioritizing consistency so we can use a no sql mongo database, that can we scaled horizontally.
we can have a url schema that holds user information as well.
So we have a load balancer distributing the server load. We have a LRU cache based system used because using a LFU here won't necessarily work as we are not sharing urls since different users will want to have different expirary dates.
When requesting the url: client hits the server, server talks to load balancer, load balancer directs the request to the correct server. We then check the reddis cache to see if the url already exists for the user, if so we pull the value and respond to the client, if not we send a request to the database for the url.
Dig deeper into 2-3 components and explain in detail how they work. For example, how well does each component scale? Any relevant algorithm or data structure you like to use for a component? Also you could draw a diagram using the diagramming tool to enhance your design...
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?