Backend system design
How to run the first ten minutes
The prompt is vague by design. Your first job is to make it precise, out loud, before you draw anything. Split what you learn into two buckets. Functional requirements are what the system does: shorten a URL, redirect a code, count clicks. Non-functional requirements are the quality attributes under load: read:write ratio, latency target for a redirect, availability of the read path, consistency you can tolerate. The non-functional bucket shapes the architecture, so pin numbers to it. "Design a URL shortener" is unanswerable; "100M writes a day, 10:1 reads, redirects under 50ms, analytics matters" has one or two reasonable designs.
Then quantify before you design. Graders read this order (clarify, estimate, draw, iterate) as the difference between a systematic engineer and someone matching the prompt to a memorized diagram.
Back-of-the-envelope estimation that interviewers grade
Convert daily volume to peak QPS, size storage, and stop. The one mistake that reliably costs you: designing for the daily average.
100M writes/day = 100e6 / 86_400 ~= 1,160 write QPS
reads 10:1 ~= 11,600 read QPS (average)
peak ~2x ~= 23,000 read QPS (design target)
storage: 100 B/row x 100M/day x 365 x 5yr ~= 18 TB
Wrong "1,160 QPS, a single Postgres box handles that fine." That is the write average. Reads are 10x higher, they spike well above the mean, and the read path is what saturates first. The estimate exists to tell you which component to worry about, not to fill time.
Composing the primitives and finding the bottleneck at 10x
You are not inventing a cache or a queue here. You are placing ones you already understand and defending each against a requirement.
client -> LB -> app servers -> cache (code->URL, immutable, ~90%+ hit)
-> DB writes + cache misses -> read replicas
async: click events -> queue -> analytics store
The cache exists because reads are 10:1 on tiny immutable rows. Replicas exist for miss traffic and read HA. The queue exists so click analytics never blocks a redirect. Every box traces to a number you stated.
Two senior details on this problem specifically. Base62 of an auto-increment id gives enumerable codes (scrapeable) and a single sequence that bottlenecks a sharded write path, so reach for a distributed id or a key-generation service; 62^7 is about 3.5 trillion codes. And 301 lets the browser cache the redirect, cutting load but erasing per-click analytics, while 302 keeps every hit at your service. Pick against the requirement.
When the interviewer says "now 10x," the cache still holds the reads. The pressure moves to write throughput, id generation, and hot codes landing on one cache node. Say where it moved and what you would reach for next. Naming the next bottleneck before you are asked is the signal that separates a senior answer from a correct one.
beta
The interviewer part is in the works.
The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.