Requirements
Functional Requirements:
- Create a short URL for a given long URL.
- Return the long URL associated with a given short URL.
Non-Functional Requirements:
- Scalability: the system should be able to support many users CONCURRENTLY shortening their URL. Horizontal scalability is very important: if there is a burst of a lot of users, the system should be able to meet the demand.
- Latency: the latency should be low-latency, but doesn't need to be real-time. Something like 1500ms as P95 should suffice.
- Availability: the system should be always available. Many nodes should be available, because of how simple this task is
- Reliability: the system should be 100% reliable.
- Consistency: data should be consistent and saved in a database, with backup nodes
- Efficiency: the system should be efficient
API Design
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...
The write path should be when the user shortens their URL, it should generate the short-url and write it in the DB.
The read path should be when the user enters in the short url, it should read it from the database, get the long url, and redirect to that website.
High-Level Design
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.
High level design:
Client: sends URL creation request to server, and redirect requests to server
API Gateway: handles the routing, rate limiting
URL Service: Validates long urls, generates short URL, stores the mappings
Redirect service: looks up short code, returns the redirect. this needs to be very fast
Cache (Redis): stores hot mappings from short to long form url
Database: stores all mappings
ID Generation: ID generation should be unique to avoid collisions. This can be done with incremental + base62 encoding
Analytics: Tracks latency, other metadata
Detailed Component Design
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
Lets look into Analytics. Analytics should do some very basic tracking, just like latency. Too much metadata means added latency, and this is a basic service. Cache hit, cache miss should be tracked.
Another key component is the ID generation. This should be done with something like a Snowflake-style id generator. What it should NOT be is a DB auto-incrementing ID generator, because it can break down with larger scale. Snowflake-style uses machine ID and timestamp to encode, which will be guaranteed to be unique.
Finally, the Redirect service: The cache hits and misses will be crucial to understand. The flow should look like:
- receive short code
- query cache
- cache hit -> give long form url for redirect
- if miss, query DB
- populate cache
- redirect