EasyStarter

URL Shortener

DatabasesCachingAPI Design

Problem Statement

ShortSnap wants to build a URL shortener similar to Bitly. Core features:

- Shorten URLs - given a long URL, generate a unique short code (e.g., `short.sn/abc123`). Users can optionally provide a custom alias.Redirect - when someone visits the short URL, redirect them to the original URL with a 301/302 response. This must be fast (< 50 ms).Click analytics - track clicks per link: total count, clicks over time, referrer, country, device type.Expiration - links can optionally expire after a set date.Rate limiting - prevent abuse by limiting URL creation to 100 per hour per user.

The service handles 1 million short links and 10 million redirects per day.

What You'll Learn

Design a URL shortening service (like Bitly) that creates short links and tracks click analytics. Build this architecture under realistic production constraints, then validate tradeoffs in the design lab simulation.

DatabasesCachingAPI Design

Constraints

Total short links~1,000,000
Redirects per day~10,000,000
Redirect latency< 50 ms
Short code length6-8 characters
Analytics delay< 5 minutes
Availability target99.9%
ApproachClick to expand

Interview-Ready Approach

1) Clarify Scope and SLOs

  • Problem statement: Design a URL shortening service (like Bitly) that creates short links and tracks click analytics.
  • Design for a peak load target around 579 RPS (including burst headroom).
  • Total short links: ~1,000,000
  • Redirects per day: ~10,000,000
  • Redirect latency: < 50 ms
  • Short code length: 6-8 characters
  • Analytics delay: < 5 minutes

2) Capacity Planning Method

  • Convert traffic and growth constraints into request rate, storage growth, and concurrency budgets.
  • Keep at least 2-3x safety margin per tier (ingress, compute, storage, async workers).
  • Reserve explicit latency budgets per hop so p95 can be defended in review.

3) Architecture Decisions

  • Databases: Define a clear system-of-record and design read/write paths separately before adding optimizations.
  • Caching: Put cache on hot read paths first and pick cache-aside or write-through explicitly.
  • API Design: Standardize API boundaries, idempotency keys, pagination, and error contracts first.

4) Reliability and Failure Strategy

  • Use strong write constraints (transactions or conditional writes) and explicit backup/restore strategy.
  • Bound staleness with TTL + invalidation hooks for critical entities.
  • Apply strict input validation and backward-compatible versioning.

5) Validation Plan

  • Run one peak-load test, one dependency-degradation test, and one failover test.
  • Verify idempotency for all retried writes and async consumers.
  • Track user-facing SLOs first: p95 latency, error rate, and successful throughput.

6) Trade-offs to Call Out in Interviews

  • Databases: SQL gives stronger transactional guarantees; NoSQL often gives better write scaling and flexibility.
  • Caching: Higher hit rate cuts latency/cost, but stale data and invalidation bugs become primary risks.
  • API Design: Rich APIs improve developer speed but can create long-term compatibility burden.

Practical Notes

  • Base62 encoding (a-z, A-Z, 0-9) of an auto-increment ID gives short, unique codes. 6 characters = 56 billion combinations.
  • A Redis cache in front of the database makes redirect lookups extremely fast.
  • Log click events to a queue (Kafka/SQS) and aggregate analytics asynchronously - don't slow down the redirect.

Learn the Concept

Practice Next

Reference SolutionClick to reveal

Why This Solution Works

Request path: The solution keeps ingress, service logic, and stateful dependencies separated so each layer can scale independently.

Reference flow: Web Clients -> API Gateway -> API Service -> Primary SQL DB -> Redis Cache

Design strengths

  • Cache sits on the read path to absorb repeated queries and keep DB pressure stable.

Interview defense

  • This design makes bottlenecks explicit (ingress, core compute, persistence, async workers).
  • It supports progressive scaling without re-architecting the core request path.
  • It keeps correctness-sensitive state changes in durable systems while offloading background work asynchronously.