I am expecting this is a global product, therefore I am expecting the system should handle 1000 TPS max.
Assuming a users base of 100000 with each one storing 20 URLS we need storage allocation for 2000000 URLs storage initialy. This can be scaled.
Define what APIs are expected from the system...
POST st.ly/shorten
Header - will have JWT token is user is logged in
Body
{
URL: valid URL
ExpirationTime: datetime {optional}
}
Response will be shortened URL
Response codes can be 201,503, 400
(404 or 403 is not applicable since URL shortner will not need to access the destination URL)
GET st.ly/shortenedURL
{
ShoternedURL input - validate length
}
response
{
Redirected URL
Time to expire
}
Response codes: 404, 200,503, 400
Delete st.ly/shortenedURL
{
ShoternedURL input - validate length
}
Response codes: 404, 200,503, 400
Post st.ly/register
{
emailID: valid email
Password: minimum one digit
}
Response codes: 200,503, 400
LoginAudit DB
Users Table
UserID
UserEmail
UserPasswordHash
URLs Table
UrlID
UserID
RedirectUrl
TimeToExpire
NumberOfClicks
Gateway - Load Balancing, Authentication
RegistrationService - Handles registering users, validating email
ShortnerService - core service which will handle shorten requests. Will serve create, get, delete requests. This service will also check Redis before fetching the DB
Redis Cache - will store frequently accessed URLs
BatchService - backgroup application which will periodically run and expire URLs
Client -> Gateway -> ShortnerService (check Cache) -> DB
ShortnerService is a microservice which can be scaled up and down
BatchService is a SpringBatch service
DB I want to use is relational db MYSQL
Explain any trade offs you have made and why you made certain tech choices...
When there are high number of URLs expired, we need a way to store themefficiently so that doesn't slow down the system
We can design an archive table to store all this
if any bots start using this service we have expect very high low in very short time, we need to implement rate limitting to handle this
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?