My Solution for Designing a Simple URL Shortening Service: A TinyURL Approach

by horizon_utopia550

Requirements


Functional Requirements:


in-scope:

  • Create a short URL for a given long URL.
  • Return the long URL associated with a given short URL.

out-of-scope:

  • Expiry of URLs
  • Detailed Analytics
  • Custom Aliases
  • User Authentication

Non-Functional Requirements:

  • High Reads throughout (reads>writes)
  • Low Latency Redirects <100ms
  • High Availability
  • Durable Storage for URL mappings


API Design

Define the APIs expected from the system. This is your chance to analyse and define the read and write paths so that you can come up with the high-level design...


  • POST /shorten
    • Request Body : { long_url : string }
    • Response : { short_url : string }


  • GET /{shortCode} : Behaviour 302, redirect to original long URL, or 404 if invalid



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.


Components

    • Clients
    • Load Balancer
    • Web/App Servers -> URL Service
    • Cache (Redis)
    • Database (example: MySQL / NoSQL)

Flows

    • Shorten Flow (POST)
      • Client sends long_url to the load balancer -> URL Service
      • URL Service validates the URL & generates a unique shortened URL
      • Stores the mapping (short_url, long_url, metadata) in the database
      • return the short_url to the client


    • Redirect Flow (GET)
      • Client hits the shortened/{shortCode} -> Load Balancer -> URL Service
      • URL Service first checks Cache
        • if hit, get long_url
        • if miss, query DB for long_url, update the cache
    • Return 302 redirect to long_url



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.


-> Short Code Generator

    1. Goal is to generate a unique, short URL for each long URL
    2. Approach (Base62 encoding of an id)
      1. Every new URL gets an auto-incrementing numeric id
      2. convert this id into base62 encoded string -> ( [a-z], [A-Z], [0-9] ). example : 125 -> "cb"
    3. Base62 -> compact URLs, 7-8 chars of Base62 already gives a capacity of nearly 3.5 trillion (62^7 + .. )
    4. Since the ids will be unique, short codes will be unique -> no collision


-> Data Storage & Schema

  1. use relational db
  2. Main Table (URL Table)


Column Type Notes id bigint primary key (for base62) short_code varchar unique index long_url text original created at datetime nullable at the moment
  1. Index on short_code for fast lookups in redirect path.
  2. DB can be:
    1. Single instance + replicas for early stage.
    2. Later, sharded by hash(short_code) or ID for scale.


-> Caching Layer

  1. Use Redis for hot mappings.
  2. Cache key: short:{short_code}, Value: long_url
  3. Redirect path:
    1. Check cache first → O(1) lookup.
    2. On miss, fall back to DB and set cache for subsequent requests.
  4. Eviction policies:
    1. LRU or similar; TTL can be long since URLs don’t change often.
    2. This significantly reduces DB load, since reads are much more than writes.

-> Scalability

  1. App servers can scale horizontally behind Load Balancer.
  2. Database can have read replicas for scaling reads
  3. Availability vs consistency:
    • For redirects, eventual consistency is acceptable
    • DB remains the source of truth.