1. Requirements

Functional Requirements

  • Generate short URL for a given long URL
  • Redirect short URL → original URL
  • Optional:
    • Custom aliases
    • Expiration time
    • Analytics (click count)

Non-Functional Requirements

  • Latency: < 50ms redirect
  • Throughput: High read-heavy system (~100:1 read/write)
  • Scalability: Billions of URLs
  • Availability: Very high (redirect must not fail)
  • Consistency: Eventual consistency acceptable for analytics


2. Estimations

Traffic

  • Writes: ~10K/sec
  • Reads (redirects): ~1M/sec

Storage

Assume:

  • 100B URLs over time
  • Each record ~200 bytes

👉 Total ≈ 20 TB → requires distributed storage

Read/Write Pattern

  • Highly read-heavy
  • Requires aggressive caching


3. API Design

3.1 Create Short URL

POST /shorten

Request:

{ "long_url": "https://example.com/abc", "custom_alias": "optional", "expiry": "optional" }

Response:

{ "short_url": "https://sho.rt/xyz123" }

3.2 Redirect

GET /{short_code}

Response:

  • HTTP 302 → redirect to long URL

3.3 Analytics (Optional)

GET /analytics/{short_code}



4. Data Storage & Design

4.1 Database (Primary Store)

Use:

  • Distributed KV store (e.g. Amazon DynamoDB / Cassandra)

Schema:

short_code (PK) long_url created_at expiry user_id

4.2 Cache (Critical)

Use:

  • Redis

Key:

short_code → long_url




5. High-Level Architecture (HLD)

System divided into:

5.1 Data Plane (Redirect Flow)

  1. Client hits short URL
  2. Request goes to CDN
  3. CDN checks cache:
    • If hit → redirect
    • If miss → go to backend
  4. Backend:
    • Check Redis cache
    • If miss → fetch from DB
  5. Return 302 redirect

5.2 Control Plane (Short URL Creation)

  1. Client sends long URL
  2. Service generates short code
  3. Store mapping in DB
  4. Cache in Redis






6. Detailed Breakdown

6.1 Short Code Generation

Option 1: Hashing (Not ideal)

  • Collisions possible ❌

Option 2: Counter + Base62 (Preferred)

ID → Base62 encoding → short_code

Example:

123456 → "abcD"

👉 Benefits:

  • Unique
  • Compact
  • Predictable length

6.2 Read Optimization (Critical)

  • CDN caching (edge)
  • Redis caching (hot data)

👉 Most requests never hit DB

6.3 Write Path

  • Generate ID
  • Encode → short code
  • Store in DB
  • Populate cache

6.4 Scaling Strategy

Stateless App Servers

  • No local state
  • Horizontally scalable

DB Scaling

  • Sharding by:
hash(short_code)

Cache Scaling

  • Redis cluster

6.5 Hot Key Handling

Problem:

  • Viral links → extreme traffic

Solution:

  • CDN absorbs majority
  • Redis handles remaining
  • Replication for hot keys




7. Additional Considerations

7.1 Burst Traffic Handling

  • CDN absorbs sudden spikes
  • Redis handles high QPS
  • Backend protected from overload

7.2 Cache Miss Handling

  • Redis miss → DB lookup
  • Populate cache after read

7.3 Degraded Mode

Case 1: Redis Down

  • Direct DB reads (higher latency)

Case 2: DB Down

  • Serve from cache if available

Case 3: Full Failure

  • Graceful degradation (temporary errors)

7.4 Expiration Handling

  • TTL on DB + Redis
  • Background cleanup jobs

7.5 Analytics

  • Async logging
  • Stream processing (Kafka)

7.6 Security

  • Prevent abuse:
    • Rate limiting
    • Spam detection

🏁 Final Summary

  • CDN + Redis caching ensures ultra-low latency
  • Base62 encoding ensures compact unique URLs
  • Distributed DB + sharding ensures scalability
  • Stateless services ensure horizontal scaling
  • Multi-layer caching handles extreme read load