> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# URL Shortener Requirements and the API

> Guide to designing a scalable URL shortener covering requirements, traffic estimates, API and data model, short-code generation, redirect performance, caching, analytics, and scaling tradeoffs.

Let's take a look at our first system-design interview problem.

Design a URL shortener (like Bitly). A user pastes a long URL and the service returns a short, neat URL that redirects to the original link. This is a common, real-world product: it makes long, unwieldy links easy to share.

Example flow:

```text theme={null}
https://learn.kodekloud.com/user/courses/system-design-for-interview-prep
shortlink.io/aX9dQ2z
```

Anyone who clicks the short URL is redirected to the original long URL. The problem looks simple on the surface; interviewers use this prompt because the interesting part is the design decisions and trade-offs.

We will apply a six-step system-design framework to this problem. Below we cover the first three steps: clarify requirements, estimate scale, and define the API / data model.

## Step 1 — Clarify requirements

Only ask clarifying questions that would change the design. Useful questions include:

1. Can users pick custom short links (e.g., `shortlink.io/kodekloud`) or must the system generate an opaque code?
   * If custom links are allowed, you need to check for collisions, reserve names, and possibly rate limit creations for a chosen string.

2. Do short links expire, or are they permanent?
   * If they expire, you need a cleanup pipeline and extra checks at redirect time.

3. Do you need analytics (click counts, geolocation, timestamps)?
   * Analytics introduces additional writes on redirects and often requires asynchronous logging to avoid slowing redirects.

Assumptions for this lesson:

* Custom links are NOT allowed (system-generated only).
* Links do NOT expire (they live indefinitely).
* Analytics are optional / nice-to-have (we’ll design core system first).

If custom links were supported, the UI/UX and backend must handle name reservation and conflict resolution. Example custom-link flow (kept for context):

```text theme={null}
shortlink.io/kodekloud
shortlink.io/aX9dQ2z
kodekloud
IS IT TAKEN?
RESERVE IT
```

Restate scope to the interviewer: create short links that redirect to original URLs, no custom links, links are permanent, and analytics are optional.

## Step 2 — Back-of-the-envelope estimation

Estimate only the numbers that affect design choices.

Question 1 — how many new links per day?\
Assume 1,000,000 new links per day.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/FNsK4qjOEH3p_rqy/images/System-Design-for-Interview-Prep/Warm-Ups-The-Read-Heavy-Classics/URL-Shortener-Requirements-and-the-API/estimate-step-1000000-new-links.jpg?fit=max&auto=format&n=FNsK4qjOEH3p_rqy&q=85&s=86bdd9794c85bcd5f812ddde844b415b" alt="A dark-themed app screen with a highlighted &#x22;Estimate&#x22; step showing the large text &#x22;1,000,000&#x22; and the caption &#x22;new links a day.&#x22; A small chat bubble at the bottom left says &#x22;Let's say a million a day.&#x22;" width="1920" height="1080" data-path="images/System-Design-for-Interview-Prep/Warm-Ups-The-Read-Heavy-Classics/URL-Shortener-Requirements-and-the-API/estimate-step-1000000-new-links.jpg" />
</Frame>

One million new links per day is roughly 12 new links per second — easily handled by modern databases for writes.

Question 2 — how many clicks per short link?\
Assume each created link gets \~1,000 clicks over its lifetime. This implies a read-to-write ratio of roughly 1000:1, i.e., the system is heavily read-biased.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/FNsK4qjOEH3p_rqy/images/System-Design-for-Interview-Prep/Warm-Ups-The-Read-Heavy-Classics/URL-Shortener-Requirements-and-the-API/read-heavy-1000-to-1-diagram.jpg?fit=max&auto=format&n=FNsK4qjOEH3p_rqy&q=85&s=b028da699bb00ff6b0fe898c7d6c0918" alt="A dark-themed diagram showing a single pink user writing to a pair of servers that fan out to many teal reader icons labeled &#x22;1000 reads.&#x22; The graphic is captioned &#x22;Read heavy, 1000 to 1&#x22; with side notes about writes per second." width="1920" height="1080" data-path="images/System-Design-for-Interview-Prep/Warm-Ups-The-Read-Heavy-Classics/URL-Shortener-Requirements-and-the-API/read-heavy-1000-to-1-diagram.jpg" />
</Frame>

<Callout icon="lightbulb" color="#1CB2FE">
  Because reads dominate writes by several orders of magnitude, prioritize optimizing the redirect path: reduce latency, add caching (CDN or in-memory), and design for horizontal read scaling.
</Callout>

Question 3 — how many links will exist in total?\
At 1,000,000 new links/day for 10 years, you approach \~3.65 billion records. That influences storage choice, indexing, and sharding strategy.

Quick summary of design-relevant numbers:

| Metric | Assumption | Result / Impact |
| - | - | - |
| New links/day | 1,000,000 | \~12 writes/sec — modest write load |
| Reads per created link | 1,000 | Heavy read amplification (read-heavy) |
| Total links (10 years) | 1,000,000/day × 3650 days | \~3.65 billion rows — influences sharding & storage |

## Step 3 — Define the API and data model

At minimum the service needs two endpoints:

* Create a short link (POST): client sends a long URL, server returns a short code or full shortened URL.
* Redirect (GET): browser requests the short URL, service responds with an HTTP 301/302 redirect to the long URL.

A simple key-value mapping (short\_code -> long\_url) is sufficient: the short code is a small key used to fetch a single value.

Example minimal API:

```http theme={null}
POST /api/v1/shorten
Content-Type: application/json
Body: { "long_url": "https://example.com/very/long/path" }

Response: { "short_url": "https://shortlink.io/aX9dQ2z", "code": "aX9dQ2z" }
```

```http theme={null}
GET /aX9dQ2z
Response: 301 Location: https://example.com/very/long/path
```

API endpoints table:

| Endpoint | Method | Description |
| - | - | - |
| `/api/v1/shorten` | `POST` | Accepts JSON `{ "long_url": "<original_url>" }`, returns short code and short URL. |
| `/:code` | `GET` | Redirect endpoint; looks up `code` and responds with `301` to stored long URL. |

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/FNsK4qjOEH3p_rqy/images/System-Design-for-Interview-Prep/Warm-Ups-The-Read-Heavy-Classics/URL-Shortener-Requirements-and-the-API/urls-table-shortcode-longurl-diagram.jpg?fit=max&auto=format&n=FNsK4qjOEH3p_rqy&q=85&s=420a359905fcdc38c617c2c490620692" alt="A stylized diagram of a &#x22;one to one&#x22; URLs table showing columns short_code and long_url with example shortcodes mapped to full URLs and arrows labeled &#x22;KEY&#x22; and &#x22;VALUE.&#x22; Two small icons labeled &#x22;INTERVIEWER&#x22; and &#x22;YOU&#x22; sit in the bottom corners." width="1920" height="1080" data-path="images/System-Design-for-Interview-Prep/Warm-Ups-The-Read-Heavy-Classics/URL-Shortener-Requirements-and-the-API/urls-table-shortcode-longurl-diagram.jpg" />
</Frame>

Storage choice recommendations

* Access pattern: single-key lookup on short\_code -> long\_url. No complex joins or transactions needed.
* Start simple: a relational database (Postgres) with an indexed `short_code` column is reasonable for moderate scale: durability, secondary indexes, and easy operations.
* For large scale (billions of rows, huge read traffic): consider sharding by code prefix or migrating reads to a distributed key-value store (e.g., DynamoDB, Cassandra) and adding caching layers.

Design considerations and next steps

* Short-code generation
  * Fixed-length Base62 (alphanumeric) codes give compact URLs.
  * Options:
    * Random codes (check for collisions; regenerate if collision).
    * Sequential IDs encoded in base62 (no collisions but predictable).
    * Hashing the long URL (handle collisions and length).
  * Ensure collision handling and consider partitioning strategy for generation if distributed.

* Redirect performance
  * Cache hot mappings in-memory (Redis or in-process LRU) and/or use a CDN/edge-cache for redirects.
  * Serve redirects from edge locations when possible to minimize latency.

* Analytics
  * Don’t write synchronous counters on redirect (this can throttle redirects). Instead:
    * Emit lightweight events to a queue (e.g., Kafka) and process asynchronously.
    * Aggregate click counts into a separate analytics store.

* Consistency and durability
  * Writes (create short link) should be durable; on create return only after persistence to avoid losing mappings.
  * Redirect reads can be eventually consistent if you accept a brief window where a newly created link might not immediately redirect (but typically prefer immediate availability).

* Scaling and availability
  * Read-heavy workloads: scale read replicas or use a cache tier.
  * Partition data (shards) once single DB throughput becomes a bottleneck.
  * Use monitoring and autoscaling for the redirect service to handle flash crowds.

Further reading and references

* [PostgreSQL Documentation](https://www.postgresql.org/docs/)
* [Designing Data-Intensive Applications (Martin Kleppmann)](https://dataintensive.net/)
* [Base62 encoding overview](https://en.wikipedia.org/wiki/Base62)

This completes the initial requirements, estimations, and API/data-model design for a basic URL shortener. Next steps in a full interview would include sketching the system architecture diagram (load balancer, app servers, cache, DB, queue for analytics), defining failure modes and mitigation, and detailing operational concerns (backups, migrations, monitoring).

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/system-design-for-interview-prep/module/bf4e82c2-1292-42c6-b85f-8b6a0dad559f/lesson/054bc911-8a2e-472d-950f-4c76c3cadb25" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.