creating user can create a shortened link
creating user can view visit counts/statistics of created link
visiting user is redirected to original link
system is available
eventual consistency is fine
amount of link visits are recorded
1 million users creating an average of 20 links each
incoming links are 500 bytes, with link records at 700 bytes
700b*20m links
14,000,000,000bytes ~ 14gb /yr
visits:
20 million users, 2/day
40 million links/day
40,000,000/100,000=400/second
Objects: user, links
APIs:
POST /link/
{
url:
}
returns id
GET /link/
{
url:
visits:
created:
}
/v/
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...
user:
id
link:
id
orig url
shortened url
creator id
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...
Database: postgres or a nosql. We'll go with nosql for scaling ease.
The links likely have a recency bias, so keeping the mush of the likely used data in cache is possible.
Use LRU cache
Server is stateless and can be easily scaled up
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...
Link creation:
client authentication happens with gateway, they POST their new link to the API server which then stores the new link and its generated shortened link in the DB and cache.
LInk visit:
User visits link, server takes the shortened link and finds the original link, redirecting the user to the original link.
visit is logged for the link, incrementing the visit count on the link.
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...
API server, scales well. Only the algorithm to generate a shortened URL is novel.
Redis cache, db scales well.
Redis utilizes LRU cache to evict unused data.
This service can also be regionalized allowing different regions to scale separately
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
Heavy visit activity would product a large number of writes for visits.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?
A couple options: store the visits in redis and have the those visit values update the db as a batch on a cadence
Log visits in a queue, or use kafka stream to aggregate the visits and update the database visits every 1-5 minutes.