List non-functional requirements for the system...
Estimate the scale of the system you are going to design...
Define what APIs are expected from the system...
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...
We definitely need a URL service that is stateless, so that it's horizontally scalable for high load; a load balance will also help balance traffic to the different servers
For commonly fetched short URLs, we want a cache that the server can access that will return the long URL
A couple ways to do this - we can either have the requests cache in the service itself in memory and have requests go to specific servers based on potentially a hash of the short URL - but that has its own issues (ie. when a server goes down, we'll instantly get a bunch of cache evictions & misses on the new server that handles this)
Better way to scale is to use redis
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...
Short URL creation Req:
Short URL access req:
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...
We need a secondary index on the database to quickly look up based on short URL.
Also for the URL shortening logic, we have a couple of options.
1) Use a hashing function to hash the long URL to a short URL; but this could create hash collisions, so when that happens we need to pad the long URL with additional characters until the collision is gone
2) Use a base62 conversion on an auto incrementing ID in the database table; this won't have any collisions as we're converting on the auto ID which is guaranteed to be unique; a couple of changes to the database schema for this to work: we need an auto incrementing ID as the primary key, and then an secondary index on the long URL
Explain any trade offs you have made and why you made certain tech choices...
load balancer -> api gateway to handle rate limiting & if we ever want user accounts can use that for auth
stateless server w/ a distributed redis cache to scale horizontally
sql over no sql for acid & transactions; more reads than writes so single leader replication is fine
Try to discuss as many failure scenarios/bottlenecks as possible.
With multiple servers there could be a race condition when the same requests come in to create a short URL for the same long URL; these servers don't see the entry for the long URL so they all attempt to write into the database table
We can solve this by putting a unique constraint on the long URL column, so any server thaat attempts to insert the same long URL the second one will fail
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?