Chaturmind
LearnDSASystem DesignBlogPremium
Sign inGet started
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML

Company

  • Blog
  • Premium
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.

System Design›Design a URL Shortener
URL Shortener

Design a URL Shortener

hashingdatabasescachingdistributed-systems

Problem Statement

Design a URL shortening service like bit.ly. Users submit a long URL and receive a short alias (e.g., short.ly/xK9p2). Clicking the short URL redirects to the original.

Requirements

Functional

  • ✓Given a URL, generate a unique short alias
  • ✓Redirect short URLs to the original long URL
  • ✓Short links expire after a configurable TTL
  • ✓Users can optionally provide a custom alias

Non-Functional

  • ✓High availability (99.99% uptime)
  • ✓Redirection latency under 10ms at p99
  • ✓100M new URLs per day write throughput
  • ✓10B redirects per day read throughput

Capacity Estimation

Capacity Estimation

Write throughput: 100M URLs/day ≈ 1,160 writes/sec

Read throughput: 10B redirects/day ≈ 116,000 reads/sec → read:write ratio ~100:1

Storage: Average URL = 500 bytes. 100M × 365 × 5 years × 500 bytes ≈ 90 TB over 5 years

Short code length: Base62 with 7 chars → 62^7 ≈ 3.5 trillion unique codes. Enough for centuries.

High-Level Architecture

High-Level Architecture

Client
  │
  ▼
Load Balancer
  │
  ├── Write Service  → generates short code → writes to DB + cache
  └── Read Service   → looks up short code → 301 redirect
                              │
                        [Redis Cache]  →  [Cassandra / DynamoDB]

Key insight: reads vastly outnumber writes. Optimise the read path with an in-memory cache (Redis). The cache is populated on first read and expires with the URL's TTL.

API Design

API Design

POST /api/v1/shorten
Body: { longUrl, customAlias?, ttlDays? }
Response: { shortUrl, expiresAt }

GET /{shortCode}
Response: 301 Redirect to longUrl
          404 if not found or expired

Database Design

Database Design

url_mappings
  shortCode   VARCHAR(8)   PK
  longUrl     TEXT         NOT NULL
  userId      VARCHAR(36)  nullable
  createdAt   TIMESTAMP
  expiresAt   TIMESTAMP    nullable (null = never expires)

Why Cassandra / DynamoDB? The access pattern is key-value: lookup by shortCode. Wide-column stores are optimised for this and scale horizontally. PostgreSQL works fine at smaller scale.

Scaling Strategy

Scaling Strategy

  1. Cache first: Redis holds the hot 20% of URLs that serve 80% of traffic
  2. Read replicas: Route all redirect traffic to read replicas; writes go to primary
  3. CDN edge caching: For ultra-popular URLs, cache the redirect at edge nodes to reduce latency to <1ms
  4. Partitioning: Shard Cassandra by shortCode hash for even distribution

Trade-offs

  • Base62 vs MD5 hashing: Base62 counter is simpler and avoids collisions; MD5 is faster but requires collision handling.
  • 301 (permanent) vs 302 (temporary) redirect: 301 allows browsers to cache the redirect (fewer server hits), but you lose click analytics. Use 302 if click tracking matters.

Bottlenecks

  • Short code generation at scale: A single counter is a bottleneck. Solution: pre-generate batches of codes per application server.
  • Cache stampede: If a popular URL's cache entry expires, thousands of simultaneous cache misses hit the DB. Solution: probabilistic early expiration.

Failure Scenarios

  • DB unavailable: The read service can still serve cached URLs. Write service fails gracefully with 503.
  • Cache unavailable: Fall through to DB. Performance degrades but the service stays up.