List functional requirements for the system (Ask the chat bot for hints if stuck.)...
There is many other functional requirements that we could set here is goals like link expiration, analytics, anti-buse for bad URLs, paid subscriptions, private URLS etc. but I will set these as main ones aimed in this design.
List non-functional requirements for the system...
Estimate the scale of the system you are going to design...
This is not a massive traffic, and a system that reasonably scales horizontally will attend this demand.
Define what APIs are expected from the system...
GET /{shortened_url_id} -> redirects to the shortned URL
PUT /shorten?url={url_to_be_shorten} -> return the shortened URL and metadata.
User related operations:
POST /account/auth, POST /account/create, GET /account/info
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.
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...
The first component needed is a reliable and scalable DNS service, as usually the users that access a shortened a URL didn't accessed the domain recently and their recursive DNS servers may not have the domain cached.
The first step, looking from the overview of the client, would be a CDN. CDNs already have a globally distributed network with HTTP caching built-in. With a CDN, the shortened URL response (the redirect) can be cached around the globe with minimal complexity and without the need to deploy our own cache.
Backing the CDN we should have an API Gateway that would be useful to distribute the traffic to a set of microservices. This microservices would be:
The shorten URL service, composed by:
The account service, composed by:
We also need a message broker to propagate the changes from one microservice to another. We could use a Kafka service to propagate the users changes (new accounts, profile updates, blocks etc.) to the shortening microservice database.
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...
The request will flow to different paths depending on the type of request.
If it is a request to a shortened URL, the first step will be at the CDN that will check if the URL is cached in the POP it is being accessed. If yes, it will provide the answer to the client directly from the edge. Otherwhise, the request will flow through the shorten URL service that will answer the redirected URL.
For the other operations, there will not be caching at the CDN and the requests will flow to the respective service.
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...
As describe on the high-level design, I tried to use managed services that are high scalable, available and with a very low latency. This way we can avoid management complexities and achieve the non-functional requirements.
Try to discuss as many failure scenarios/bottlenecks as possible.
In the case of failures in the CDN or API Gateway our entire system would be down. We can avoid this by deploying stand-by a stand-by CDN in another provider and a stand-by API Gateway in another region.
As the services are microserviced, a failure in one service would not affect the anothers, decreasing the impact area. The cache on the CDN for shortend URLs would also help a lot in case of an outage in the shorten URL service.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?
For every system we need a very robust observability and alarming capabilities. We could also add many more features and distribute this features into another microservices.