Assumptions: Login, sso, auth, and basic security gates are in place and we are not designing any of them as part of this problem.
User-creator should be able to create a new short link by providing a long link.
User-consumer should be redirected to the correct link after clicking on the short link
User-creator should be able to update long link associated with short link
User-creator should be able to share short link
Stretch requirements:
User-creator should be able to see number of clicks on short link
User-creator should be able to delete or deactivate short link
We have a read heavy app, so reads need to be fast and writes can be slower.
Read Latency P99 < 1s
Write latency P99 < 5s
Uptime - 99,99%
DAU: 2000
Peak DAU: 2000 x 5 = 10000
We can tolerate eventual consistency
Multi-region availability
Estimate the scale of the system. Consider daily active users, read/write ratio, storage requirements, bandwidth, and any relevant QPS calculations...
As dau is 2000 and we would estimate that half of them would create links, our write payload on average would be 2KB considering the link and metadata.
Write 2KB * 1000 = 2mb per day. 2MBs * 365 approximately 750mb or 1gb per year rounded.
Writes after 5 years total storage - 5GB
1000 creations/day ÷ 86,400s ≈ 0.012 writes/s
R/W = 10/1, at peak X5 50/1
Following the 80/20 storage distribution rule, 20% for total storage should be allocated for RAM/Cache = 1GB.
Define the APIs expected from the system. This is your chance to analyze and define the read and write paths so that you can come up with the high-level design...
POST /api/v1/urls Body: { "longUrl": "https://example.com/very/long/path", "customAlias": "promo", "expiry": "2025-12-31T00:00:00Z" } Resp: 201 Created { "shortUrl": "https://tiny.url/aB3xK9", "longUrl": "...", "createdAt": "..." }
customAlias and expiry optional; longUrl required.GET /{shortCode} Resp: 302 Found Location: https://example.com/very/long/path
302 chosen so we could enable analytics later
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
Very high level design: Client - API - DB
Client for User-creator has the ui, user-consumer send queries to API by clicking on the link.
API is responsible for both reads and wrights, tls termination and load balancing
When write request is submitted, algorithm converts long url into short and sends a write request to DB with long, short, and time of update.
Algorithm would use Counter + Base62 Encoding:
When read request is submitted, api sends a query with short link to db, and returns a longURL
We can improve this design by adding a db replications, load balancer and cache.
Load balancer would distribute POST and GET requests into read and write buckets. Reads would go to read DB, writes to write DB. Loadbalancer would disctribute reads between DB replicas and perform health checks. Reads would check cache before hitting db
Define the data model. Identify the main entities, their attributes, and relationships. Consider the choice of database type (SQL vs NoSQL) and justify your decision based on access patterns...
We will go with noSQL to support TTL and native scaling
table name: longToShortURLS
Columns: LongURL(String) PK, ShortURL(String) , LastUpdateTime(DateTime)
Index on ShortURL
Partition on hash of shortURL
Strong consistency on writes
Eventual consistency for reads
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
Read path / cache - we would add before the read dbs. Implement indempotency to avoid sending hoard of queries to DB on miss. One query will go through to read from DB and update cache. Also a good idea to implement Jittered TTLs and Probabilistic Early refresh
regarding cache failure - latency would degrade, but we have read replicas, so system would still be available. We can also create a cache replica, if resources allow and let load balancer decide which cache to use - however it adds complexity.
the encoding of short codes id use Sequential + base62 and would obfuscate it to make codes non guessable