Shortened URL storage will also include an index on original URLs, so that the service can check efficiently if there's already a shortened URL present.
We have a pretty simple design:
We have two main flows to cover:
For the first one a request first goes to a load balancer and is dispatched to a proper instance (taking current load into consideration) of a shortener service, which generates a new one, puts it in the DB. Then it returns the result to the user.
For the second case a request also starts from going to the load balancer, but then it gets routed to a redirection service. It first checks its own cache and if the record for the shortened url cannot be found goes to the DB and then either returns an error to the user or puts the original URL to cache and redirects the user.
Redirection service will use a MD5 hashing algorithm for shortening URLs. It will only take first 7-8 characters from a hash to use as a key. If we have a collision here, we that rehash current full MD5 hash again, until we get rid of collisions. And only then we add a new record to the DB.
Shortener service will not add records to the cache since we would expect less shortening requests and more redirection ones.