we will have two APIs
We will have a database, where the schema has two columns: tinyURL (or just the generated ID), and longURL (i.e. the url to redirect to).
We can shard the database by the generated ID.
we will have a api gateway and a load balancer to distribute the request to corresponding service: generationService, and redirectionService. generationService handles the put request; redirectionService handles the get request.
we will also need a unique ID generator for the for the ID.
A database storing the mapping.
Caching layer for the redirection service -> storing 'hot' tinyURL to reduce latency and DB read.
say a user wants to create a tinyURL for a long URL. she sends a put request. The request first handle by an API gateway and forward the request to the load balancer. The request is then forwarded to the generation service where a unique ID is generated, then the mapping is store in the DB.
now the user enters the tinyURL to the browser, the browser sends a get request to the API gateway and forward to the load balancer, then to the redirection service. The redirection service checks if the tinyURL is in the cache, if it is, then the api gateway sends a 301 http response with the long URL. If the mapping is not found in the cache, the service then access the DB.
let's deep dive into the unique ID generator.
First of all, what should the length of the ID be? Because we are storing 100M URL. Let's use base-62 to convert int -> string. We need 5 character.
we can use timestamp to create unique ID, and for each node we append a node ID to the timestamp so it ensures each ID is unique. Then we use base-62 encoding to transform the ID to string of 5 alphanumeric characters.
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?