Estimate the scale of the system you are going to design..
Provided we have a monthly active user count of 1 million, expecting each user to create 5 URLs on average each day. We will need to store 5 million URLs in our database, if we keep the expiry of the URLs to not exceed 1 day. Assuming 2KB data to be store for each mapping, our database size would be approximately - 100,00,000 KB = 10000 MB = 10GB.
On the read front, if there are 5 million URLs, and each URL is accessed about 10 times on an average in a day, we have around 50 million requests in a day, which translates to 2 million requests in an hour, which is 30K requests per min, which is 500 request per second.
Define what APIs are expected from the system...
Body
{
"fullURL" : string,
"preferredPrefix" : string,
}
Returns 200 OK
{
"tinyURL" : string,
"createdTime" : datetime,
"expiryTime" : datetime
}
Return 400 Bad Request if fullURL is invalid
Return 404 Not Found if preferredPrefix is not available.
Returns 200 OK
{
"fullURL" : string,
"createdTime" : datetime,
"expiryTime" : datetime
}
Return 404 if tinyUrl is not found
Body
{
"tinyUrl": string,
"startTime": datetime,
"endTime" : datetime
}
Returns 200K
{
"timesAccessed": number,
"lastAccessedTime": datetime
}
Return 404 not found if tinyurl not found
Return 400 Bad request if time frame is invalid
Defining the system data model early on will clarify how data will flow among different components of the system. Also you could draw an ER diagram using the diagramming tool to enhance your design...
We will use a SQL database here to store the data as strong consistency is required here. And there's a clear relationship in the table we will define.
First table will be called 'Users' which will store user information. Columns :
Another table will store all the urls called "URLInfo". Columns :
Then, there will be browser session cache, where the key value pair would be tinyURL and fullURL.
Then, we have a redis cache. First, it will have keys like "UserId_FullUrl" and it's value will be "TinyUrl".
Then we have keys like "tinyUrl" and it's value will be "FullUrl".
You should identify enough components that are needed to solve the actual problem from end to end. Also remember to draw a block diagram using the diagramming tool to augment your design. If you are unfamiliar with the tool, you can simply describe your design to the chat bot and ask it to generate a starter diagram for you to modify...
End users will use the clients ( browsers, mobile browsers ) to interact with a GUI that will allow them to perform the functionalities they want.
Client tries to handle the queries using browser cache if possible.
If not, Client makes HTTPS request to the load balancer of the service.
Load balancer routes the request to the right server depending on the affinity and the existing load on servers. This would ensure good performance of APIs.
The server tries to retrieve the result from redis cache if possible. If not, we go to the database, and cache the result on the way out.
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
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?