Here we will place load balancers for receiving all requests. They will route to frontend service which will be in change of validating users (i.e. will use redirection to IDP, validate the JWTs generated by the IDPs), routing shortening requests to shortening service. A separate set of load balancers will handle the actual traffic of the short_url endpoints. These will route to redirect services. All of these services will be stateless and use kubernetes horizontal pod autoscaling based on load (i.e. configured at CPU / memory thresholds).
The redirect services shall query Redis cache to see if caches contain the URL mapping. If not, these we get directed to the DB for lookup. If not in cache, the application will search the correct shard and then cache the mapping after it finds it. It can read from read replicas here. It's ok not to use the leader (i.e. write replicat). These services will handle much more traffic than the shortening service and thus number of servers should be sized higher.
The shortening service will first lookup the long_url and see if it exists. It firsts looks at the bloom filter if it is found and if found, checks whether it's a false positive by looking in the appropriate DB. If so, then it looks up the short_url and returns that. If not found, then it generates a random short URL and looks it up for ensuring it doesn't already exists. We can generate these in advance if necessary, but don't expect to get too many conflicts. Next, it will update the cache with the mapping (assumes that users will want to test and we want to maximize speed for enhanced performance initially).
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?