11. How would you design a URL shortening service?
Design a URL shortening service with unique aliases, redirect handling, collision avoidance, and scale considerations.
At a high level, this service turns long URLs into short links and quickly redirects users to the original page. The main challenge is keeping every alias unique while making the read-heavy redirect path fast. I would explain it in two main flows: creating a short link and redirecting an existing one. Stateless Java replicas handle requests, the Primary Database stores the official mapping, and the Distributed Cache speeds up redirects. The trade-off is that cached or replicated reads can briefly be behind the primary data.
The goal is to turn a long web address into a short alias. Later, anyone opening that alias should reach the original address very quickly. The hard part is balancing correctness and speed. New aliases must not conflict with existing ones, while redirects happen often and should stay fast. The diagram separates these concerns into a create path and a redirect path. It also moves optional click analytics into background work, so recording clicks does not slow the main redirect response.
- Should users be allowed to choose their own custom aliases?
- How much larger do we expect redirect traffic to be than create traffic?
- Do we need click analytics for every redirect?
I would start by saying both flows use the same entry layer. DNS resolves the service address, and clients connect using HTTPS. The Load Balancer / API Gateway then sends requests to the URL Service.
The Guardrails can apply API Key / Tenant Auth when needed. They also provide Rate Limiting, URL Validation, and Alias Validation. An invalid URL or alias returns 400. An existing custom alias returns 409. A request over the rate limit returns 429.
For the create path, the client sends POST /shorten. The request contains a long URL and may include a custom alias.
A stateless Java 21/25 URL Service handles the request. Inside a JVM replica, the REST Controller sends it to the Shorten Handler. If a custom alias was supplied, the Alias Generator validates its uniqueness. Otherwise, it generates a random Base62 token, checks whether that token already exists, and retries after a collision.
The Mapping Repository writes the alias and long URL to the Primary Database. The database has a UNIQUE(alias) index, which is the final collision protection. After the database write succeeds, the Cache Client updates the Distributed Cache. The service then returns a JSON response containing the short URL.
For the redirect path, the client sends GET /{alias}. The Redirect Handler asks the Distributed Cache for the long URL first.
On a cache hit, the long URL is returned quickly. The service then sends an HTTP 301 or 302 redirect to the client.
If the cache misses, the service performs a SQL read for the alias. The read can use the Primary Database or the optional Read Replica. When the mapping is found, the service puts it into the cache and returns the redirect. If the alias does not exist, the client receives 404.
The URL Service runs as multiple stateless JVM replicas. Separate JVM replicas do not share heap state. This lets the Load Balancer / API Gateway spread requests across more replicas as traffic grows.
The Primary Database remains the source of truth and handles all writes. The optional Read Replica receives data asynchronously from the primary and can serve extra lookup traffic. Because that copy happens later, it can be slightly behind the primary.
Click analytics is optional and stays outside the critical redirect path. The service can send a click event to the Event Queue / Stream. The event then goes to the Analytics / Metrics Sink in the background.
Redirect traffic is read-heavy, so the Distributed Cache removes many reads from the database. The cache can be repopulated after a miss, but it may briefly contain older data.
Random Base62 tokens are simple to generate, but collisions are still possible. The service therefore checks for an existing token and retries. The database unique index remains the final protection.
Metrics, Structured Logs, Distributed Tracing, and Alerts help operate the system. They show request rates, errors, cache behavior, database latency, JVM health, and other failures without changing the main request flow.
The benefit is that redirects stay fast because the Distributed Cache handles many repeated lookups. Stateless JVM replicas also make it easy to add more service capacity. The downside is that cached data can briefly be older than data in the Primary Database. The optional Read Replica can handle extra reads, but it may also be slightly behind because replication happens asynchronously. Random Base62 tokens are easy to create, but collisions can happen. We accept that because the service retries, while the UNIQUE(alias) index gives the database a final safety check.
Interviewers use this problem to see how you split a system into clear flows and choose where correctness matters most. They want to see whether you can make a read-heavy path fast without losing unique aliases. They also test your judgment around caching, database ownership, replicas, background analytics, rate limits, failures, and the trade-offs between speed, simplicity, and correctness.









