I am assuming a large scale system. Taking the DAU to be around 1M DAU.
Assuming the reads to write ratio is around 5:1 ==> 5 reads per write
Therefore this is a read heavy system
CREATING A TINYURL:
POST /createTinyUrl --
{userId, timestamp, bigURL}
RESPONSE 200 success with data
{
messaage: success
result:
}
REDIRECTING A TINY URL
GET
RESPONSE 300s
redirect back to the original URL
MONITOR
GET /popularURLs?minHitCount=1000
RESPONSE
[
{ url: bigURL1},
{url: bigURL2}
]
I will have one DB : TinyURL DB with tables like
URL table : UserId, TimeStamp,BigURL, TinyURL, count ==> roughly 300 bytes/record
Key DB: Available Hashes ==> roughly 8bytes/ hash ==> 8 bytes* 10^6 hashes ==> 8MB; we will reuse them as well
For keys DB we can use (in-memory DB) Redis and the TinyURL DB can be a No-SQL DB (like DyanmoDB/ mongoDB) as eventual consistency is a good trade-off here while guaranteeing high availability and scalability
Client goes through the AWS managed LoadBalancer layer to be able to distribute the load throughout
The request then hits the TinyURL service which then interacts with the storage layer to do the necessary operation
There is monitoring component to periodically keep pulling the popular URLs
Try to discuss as many failure scenarios/bottlenecks as possible.