· SWE Editorial · System Design  · 6 min read

Design a URL Shortener: Capacity Estimation

Back-of-the-envelope math for a URL shortener — QPS, storage growth over five years, bandwidth, and cache sizing using the 80/20 rule. The exact numbers interviewers expect you to produce on a whiteboard.

Back-of-the-envelope math for a URL shortener — QPS, storage growth over five years, bandwidth, and cache sizing using the 80/20 rule. The exact numbers interviewers expect you to produce on a whiteboard.

Why Interviewers Ask for Numbers

Capacity estimation is the part of a system design interview where vague hand-waving gets exposed fastest. Saying “it should scale horizontally” is easy; producing a defensible number for QPS, storage, and cache size on a whiteboard in real time is what separates candidates who’ve internalized distributed systems intuition from candidates who’ve memorized diagrams. This article walks through the full back-of-the-envelope math for a URL shortener, using assumptions you should state explicitly before calculating anything.

Step 1: State Your Assumptions Out Loud

Always anchor the numbers to an assumption you say aloud, so the interviewer can correct you if your scale is way off:

  • New URLs created: 100 million per year (roughly 8.3M/month — a mid-size but real product, not Google-scale, not a toy)
  • Read:write ratio: 100:1 (a conservative, commonly cited ratio for link shorteners; some products run as high as 1000:1)
  • Average long URL length: ~500 bytes (including headers/metadata overhead in storage, real URLs are often shorter but you leave room)
  • Data retention: 5 years, no deletion by default
  • Short code length: 7 characters, base62

Step 2: Queries Per Second (QPS)

Write QPS

100,000,000 URLs / year
÷ 365 days
÷ 24 hours
÷ 3600 seconds
≈ 3.2 writes/second (average)

Average write QPS is tiny — about 3 per second. But average numbers hide peak load, so always apply a peak multiplier. A common assumption is peak traffic runs 2-3x average due to daily/weekly usage patterns:

Peak write QPS ≈ 3.2 × 3 ≈ ~10 writes/second

Read QPS

Using the 100:1 read:write ratio established above:

Average read QPS = 3.2 × 100 ≈ 320 reads/second
Peak read QPS ≈ 320 × 3 ≈ ~960 reads/second (round to ~1,000/sec)

The takeaway to say out loud: ~1,000 peak QPS is comfortably handled by a single well-provisioned cache tier plus a small app server fleet — this is not a system that requires exotic infrastructure at this scale. If the interviewer bumps the assumption to a viral consumer product (1B URLs/year), redo the math live; the ratios stay the same, only the constants change.

Step 3: Storage Estimation

Per-record storage

Each mapping record roughly needs:

FieldSize
short_code7 bytes
long_url~500 bytes
created_at8 bytes
expires_at8 bytes
user_id (optional)8 bytes
Metadata/index overhead~50 bytes
Total per record~580 bytes ≈ 600 bytes

5-year projection

100,000,000 URLs/year × 5 years = 500,000,000 total records
500,000,000 × 600 bytes ≈ 300,000,000,000 bytes
≈ 300 GB over 5 years

300GB is a very manageable dataset — it fits comfortably on modern SSD-backed database instances, and even a naively unsharded single-primary database can handle this storage volume. This number matters because it tells you sharding is a read-throughput decision (driven by QPS and cache-miss load), not a storage-capacity decision, for a product at this scale. State that distinction explicitly — it shows you’re not reaching for complexity you don’t need.

Step 4: Bandwidth Estimation

Write bandwidth

Peak write QPS (10/sec) × ~500 bytes/request ≈ 5 KB/sec

Negligible.

Read bandwidth

Peak read QPS (~1,000/sec) × ~500 bytes/response (redirect + headers)
≈ 500 KB/sec ≈ 0.5 MB/sec

Even at 10x this product’s assumed scale, bandwidth for a redirect service stays in the low single-digit MB/sec range — redirects are tiny payloads (a Location header, not a page body), so bandwidth is essentially never the bottleneck for this system. Latency and QPS handling are the real constraints, not throughput. This is worth stating explicitly, since candidates sometimes reflexively over-invest in CDN/bandwidth arguments for a workload that’s actually bandwidth-trivial.

Step 5: Cache Sizing With the 80/20 Rule

This is the calculation that most directly justifies the caching architecture from the companion “Architecture Diagram and Data Flow” article, so walk through it carefully.

Assumption: 20% of unique short URLs generate roughly 80% of all read traffic (a standard Pareto/power-law assumption for link-click distributions — a small number of links go viral or get embedded in high-traffic pages, while most links get only a handful of clicks total).

To serve 80% of daily read traffic from cache, you don’t need to cache all 500M historical records — you need to cache the “hot set” being actively read today.

Daily unique reads ≈ 320 reads/sec average × 86,400 sec/day
≈ 27,648,000 reads/day (~27.6M)

Assume these reads target a working set of roughly
1M-5M distinct "actively hot" short codes on any given day
(a reasonable estimate for a product this size — the vast
majority of the 500M all-time URLs get zero clicks on a
given day)

Cache size needed ≈ 5,000,000 hot codes × 600 bytes/record
≈ 3,000,000,000 bytes ≈ 3 GB

A single Redis instance with 4-8GB of RAM comfortably holds the entire hot working set for this scale of product, with headroom for growth. This is the number that justifies “just put Redis in front of the DB” as an actual sized decision rather than a buzzword.

Summary Table: The Numbers to Have Ready

MetricValue
Average write QPS~3/sec
Peak write QPS~10/sec
Average read QPS~320/sec
Peak read QPS~1,000/sec
Storage per record~600 bytes
Total storage (5 years)~300 GB
Write bandwidth~5 KB/sec
Read bandwidth~0.5 MB/sec
Cache size (hot working set)~3-5 GB

What Changes at 10x or 100x Scale

Interviewers love pushing the numbers up to see if you scale your architecture reasoning, not just your arithmetic. At 1 billion URLs/year (10x this scenario): peak read QPS climbs to ~10,000/sec (now you need multiple cache nodes and likely database read replicas or sharding by short_code hash), storage grows to ~3TB over 5 years (still single-digit TB, still very manageable, though now you’d seriously consider sharding for operational reasons like backup/restore time rather than raw capacity), and the cache working set grows proportionally to maybe 30-50GB (still fits in a clustered Redis setup). The key skill being tested is showing your architecture degrades gracefully as each input scales, rather than falling over at some hidden threshold.

Wrapping Up

Capacity estimation isn’t about getting the exact right number — interviewers know you’re guessing at real-world constants. It’s about demonstrating you can go from a stated assumption to a QPS/storage/bandwidth figure in under two minutes, and then use those figures to justify architectural decisions (do we need sharding? how big should the cache be? is bandwidth even a concern?) rather than picking components by habit.

For 50+ system design deep-dives like this one, see The 0-to-1 SWE Interview Playbook (Amazon: https://www.amazon.com/dp/B0H256Z1MF?tag=sirjohnnymai-20). It includes fully worked capacity estimation drills for a dozen other classic interview questions, with the same assumption-first methodology used here.

Read this alongside “Architecture Diagram and Data Flow” to see exactly where these numbers plug into the request lifecycle, and “Data Model and APIs” for the schema these storage estimates are built on.

Back to Blog

Related Posts

View All Posts »

Design a URL Shortener: Data Model and APIs

The schema, REST API contracts, rate limiting strategy, and SQL-vs-NoSQL decision for a URL shortener — the implementation details interviewers probe once the high-level architecture is settled.