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:


  • low latency
  • high availability
  • horizontal scalability


API Design


Post /shorten

Body: {long_url}

Response: {short_url}


Get /url/{short_url}

Response: 301/302 for redirect



High-Level Design


Architecture:

  • Service-oriented with independently scaling services
  • stateless services, each running multiple instances
  • all services emit telemetry


Entity Data Models:


ShortUrl:

id (pk)

short_url (unique, indexed)

long_url (unique, indexed)

created_at

updated_at





Detailed Component Design


Redirect service

  • check if the short url is cached
  • on cache hit it redirects the user to the long url
  • on cache miss it fallsback to reading the db, and if the url exist it writes it to cache and redirects the user


Shortening Service

  • check if long url already exist in db, if it does it returns the short_url for it
  • if it's a new long_url, it base encodes the url into a short version
  • stores the short url into the db
  • adds the short url to cache, to get it ready for use
  • returns the generated short url back to the user



DB

  • uses synchronous replicas for strong consistency & fault tolerance
  • primary db for writes, reads from replicas
  • For horizontal scaling, the db can be sharded using the short url id as the hash key, and consistent hashing. This way the number of shards can be increased or decreased with minimal remapping required.