Note that: we will not discuss the user login and credential service here to simplify the process. With user credentials, we can improve the service by setting access groups by user id etc.
Lets assume we have 500M user (5 x 10^8) and each user create 100 TinyURLs per year, each TinyURL data chunk will be:
TinyURL =>
20 Byte (User data) + 8 Byte (TinyURLkeys) + 75(URLlength) ~= 100 Byte
total storage:
5 x 10^2 * 10^8 x 10^2 = 5 x 10^12 Byte = 5TB
if we guarantee the user lifespan to be 10 years, we need to store around 50TB of TinyURL per server.
Then, for the application server, it will be a heavy read compare to write server, likely
1 write : 50 read
if we have 100M daily active user, it will result in a QPS as:
1 x 10^8 x 10^2 / 10^5 (second) = 10^5 Byte/s = 100MB/S
We will definitely need load balancing to help reduce the overhead for this, ideally between client and application server.
// Generate URL
TINY_URL = SET(ORIGINAL_URL, CUSTOMIZED_URL = optional, USER_METADATA = optional)
// Query URL
GET(TINY_URL, USER_METADATA = optional)
// Change URL
MODIFY(ORIGINAL_URL, NEW_URL, USER_METADATA = optional)
// Delete URL
DELETE(TINY_URL, ORIGINAL_URL = optional, USER_METADATA = optional)
Cache: we can cache in different stages to help improve the sufficiency.
with above criteria, the database can be a simple relational database:
TinyURL | URL | TimeStamp
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?