The problem
You are designing a URL shortener for a popular website. Users paste long URLs and receive a short code; when someone visits the short code, they are redirected to the original URL. The service is expected to handle a high volume of redirects, especially for popular links.
You are a backend engineer tasked with designing the core system for this service.
If the system cannot keep up with traffic, users will face slow redirects or errors, damaging trust in the service.
Must hold true
- Short codes must be unique and easy to share.
- Redirects must be very fast, even for popular links.
- The system must support at least 100 million short links in its first year.
- Downtime or data loss is unacceptable for existing short links.
Functional Requirements
What the system must DO.
| Requirement | Priority |
|---|---|
| Users can submit a long URL and receive a unique, short code. | Must have |
| Visitors can use a short code to be redirected to the original long URL. | Must have |
| Each short code must be unique. | Must have |
Non-Functional Requirements
How well it must do it — latency, availability, scale. Measurable, not vibes.
| Requirement | Priority |
|---|---|
| Redirects must complete in under 100 milliseconds for 99% of requests. | Must have |
| The system should handle at least 1,000 redirect requests per second at peak. | Must have |
| Short links must not be lost, even if a server fails. | Must have |
What you learn by asking
In an interview these facts are NOT volunteered — the candidate earns them with clarifying questions. These are the answers behind this design.
| If you ask about… | The answer |
|---|---|
| How many short links will be created in the first year? | About 100 million. |
| How large is each mapping (short code → long URL)? | Each mapping averages 100 bytes (including metadata). |
| What is the expected peak redirect rate? | 1,000 requests per second. |
| How often are new short links created? | About 10 new links per second at peak. |
| What is the required redirect latency? | 99% of redirects must complete in under 100 ms. |
Capacity Estimation
Rough arithmetic turns the requirements into engineering decisions — it tells you which parts need scaling machinery and which are trivially easy. Only the order of magnitude matters.
| Quantity | Answer | How it is derived |
|---|---|---|
| Total storage required for all short links after 1 year | ~10 GB | 100 million × 100 bytes = 10,000,000,000 bytes = 10 GB |
| Peak bandwidth for redirects (if each redirect reads 100 bytes) | ~100 KB/sec | 1,000 redirects/sec × 100 bytes = 100,000 bytes/sec = 100 KB/sec |
Quick check
Without scrolling back: roughly what did we work out for total storage required for all short links after 1 year?
The architecture, built up
Nobody designs the final diagram in one stroke, so this design is built up one component at a time rather than shown finished. Start with the simplest thing that works, then add each piece and see where it attaches.
Each stage lets the numbers break the design, then fixes exactly one bottleneck with exactly one new component — and at each break you get a chance to call the fix yourself before it is revealed. You can stop reading after any stage and still hold a complete, working system in your head — that is the point.
The simplest thing that works
Start with a client, a single application server, and a database for mappings.
At first, all requests go to a single server, which handles both shortening and redirecting. The server stores and retrieves mappings from a database.
This design is easy to build and reason about, but cannot handle high traffic or fast redirects for popular links.
The design so far
Where it breaks
At 1,000 QPS, every redirect request hits the database, risking high latency and overload.
Quick check
Which single component would you add to fix that?
Reads outnumber writes 100 to 1
The fix: Add a cache—a small, fast memory for popular short code mappings.
Redirects for popular links are served from the cache, reducing database load and improving latency.
The application server checks the cache first; if the code isn't found, it falls back to the database.
The design so far
Where it breaks
A single application server can't handle all incoming requests at high QPS.
Quick check
Which single component would you add to fix that?
One app server is now the weak point
The fix: Introduce a load balancer to distribute requests across multiple application servers.
A load balancer receives all incoming requests and forwards them to available application servers.
This allows the system to scale horizontally by adding more servers as needed.
The design so far
Where it breaks
Even with cache, cache misses and less-popular links cause high read load on the main database.
Quick check
Which single component would you add to fix that?
Database becomes a read bottleneck
The fix: Add a replica database—a read-only copy to handle redirect traffic and protect the main DB.
The main database replicates all data to a read-only replica.
Application servers can read from the replica for redirects, reducing load on the main DB and improving reliability.
The finished design
The full reference design, with the reason behind every connection. When you practice, you will rebuild this from a palette that includes decoys.
Why each connection exists
- ClientLoad BalancerClients send requests to a single endpoint for distribution
- Load BalancerApplication ServerDistributes requests to available application servers
- Application ServerCacheApp server checks cache for popular codes before hitting the database
- Application ServerDatabaseStores and retrieves mappings if not in cache
- DatabaseReplica DatabaseKeeps a read-only copy for scaling redirect reads
- Application ServerReplica Database(optional)App server can read from replica to offload main DB
The design in one glance
Each stage fixed exactly one problem. If you can retell this table from memory, you can derive the whole architecture on a whiteboard.
| The design so far | What broke | The fix |
|---|---|---|
| The simplest thing that works | — the starting point | Start with a client, a single application server, and a database for mappings. |
| Reads outnumber writes 100 to 1 | At 1,000 QPS, every redirect request hits the database, risking high latency and overload. | Add a cache—a small, fast memory for popular short code mappings. |
| One app server is now the weak point | A single application server can't handle all incoming requests at high QPS. | Introduce a load balancer to distribute requests across multiple application servers. |
| Database becomes a read bottleneck | Even with cache, cache misses and less-popular links cause high read load on the main database. | Add a replica database—a read-only copy to handle redirect traffic and protect the main DB. |
Good to know — What this design leaves out — on purpose
Every real system also needs monitoring and metrics, logging and tracing, alerting and on-call, CI/CD, auth hardening and abuse limits, and a cost model. None of them appear above, and that is a choice: they sit beside EVERY system in much the same shape, so drawing them here would add the same five boxes to every problem in this library while crowding out the part that is actually specific to this one — the path a request takes and where it breaks. This is also why a metrics or monitoring block is a wrong answer in the practice canvas: it is never the thing that makes this design work. In a real interview, name these in one sentence once the data path is settled — "I would put metrics on the cache hit rate and alert when it drops" — and move on. Reaching for them before the core flow is drawn reads as avoiding the question.
API Design
Every operation traces back to a requirement — nothing extra, nothing missing.
| Endpoint | Purpose |
|---|---|
| POST /shorten | Accepts a long URL and returns a unique short code. |
| GET /:code | Redirects the client to the original long URL for the given short code. |
Quick check
Which one would you call to accepts a long URL and returns a unique short code?
Data Model
| Entity | Fields |
|---|---|
| ShortLink | code: string (Short unique code), longUrl: string (Original full URL), createdAt: datetime (Time of creation) |
Defending the Design
Interviewers close by stress-testing the design. Strong answers follow one shape: which component → what breaks there → the fix and its cost. Here are this problem's probes and the points a strong answer hits:
What happens to redirect latency if the cache is too small or misses frequently? Redirects fall back to database, increasing latency. Higher DB load can cause slower response for all requests. Popular links may experience degraded performance.
How does your design ensure no data loss if the main database fails? Replica DB maintains a copy of all mappings. Replication ensures durability and quick recovery. Writes may be paused, but existing redirects can still be served from replica.
How does the system scale to handle 1,000+ redirect requests per second? Cache serves most popular codes at memory speed. Load balancer distributes load across multiple app servers. Replica DB handles read-heavy traffic without overloading main DB.
Tip — Key takeaway
A URL shortener with high read volume must optimize for fast, scalable lookups. Caching and read replicas are essential to keep redirect latency low and handle traffic spikes. Durability and unique code generation are critical for reliability and correctness.
Common trap — Common mistakes on this problem
Relying solely on a single database for all reads, which cannot handle high QPS and becomes a bottleneck. · Using a queue for redirects, which must be synchronous and cannot tolerate the delay of asynchronous processing. · Ignoring cache design, leading to slow redirects for popular links and unnecessary database load.
You've seen the whole design — now build it yourself
The practice run walks the same steps, but YOU do the work: gather the requirements, run the numbers, wire the architecture — with an AI interviewer and per-step feedback.