shrt.design

Interview Prep

Questions That Actually Come Up

Not a quiz — a rehearsal script. Each answer is written the way you'd actually say it out loud in a room, not as a textbook definition. Click a question to expand it.

Scoping the Problem

How do you scope this in the first five minutes?

Name the three core endpoints before drawing anything — POST /api/shorten, GET /{code}, GET /api/links/{code} — and say why each earns its place: the write, the hard read problem, and the product layer that makes a redirect manageable. Then name what you're deferring — key generation, caching, rate limiting, custom domains — in one breath, and 2–3 things explicitly out of scope, like QR codes or team billing. That's what signals deliberate scoping instead of stalling.

How do you estimate scale — QPS and storage?

Walk the arithmetic out loud. "Say 10M new short links created per day — about 115 writes/sec average. But redirects are the real number: if each link gets clicked 20 times on average over its life, that's 200M redirects/day, ~2,300 QPS average and several times that at peak, concentrated on whichever links are currently popular." The number that matters is the ratio — redirects dwarfing creations by 100:1 or more — because that's what justifies caching before anything else.

Design Deep-Dives

How do you avoid collisions when generating short codes?

Hashing the long URL and truncating to 6–7 characters is the naive first answer, and it's worth starting there — then name why it breaks: truncating a hash produces collisions often enough that you need a retry loop on every write. The next step is generating random, unique codes ahead of time and pulling from a pool, which moves uniqueness-checking off the hot write path entirely. Landing on "pre-generate instead of generate-on-request" is the sentence that gets you most of the way there.

Key Generation Service →
Why 302 instead of 301 for the redirect?

A 301 (permanent) lets the browser cache the redirect and never ask your server again — faster for the user, but it means you stop seeing that click, which kills analytics. A 302 (temporary) forces the browser back to your server every time. Since click analytics is a real part of the product here, 302 is the deliberate choice — bringing this up unprompted is a small detail that signals real product thinking, not generic system design.

Redirection (Read Path) →
SQL or NoSQL for the URL mapping table?

Start from the access pattern: it's almost entirely single-key lookups by short_code, which a wide-column store (Cassandra / DynamoDB) partitioned directly by short_code serves extremely well — every redirect resolves from one partition, no secondary index. A single relational table is perfectly fine at low scale, though, so the honest answer is "start relational, move to a store partitioned by the lookup key once write/read volume forces sharding" rather than asserting one is categorically better.

URL Shortening & Encoding →
How do you handle a link that suddenly goes viral?

This is a hot-key problem — one code getting a disproportionate share of traffic can overwhelm a single cache node even though the cache overall is healthy. The fix is detecting keys that are getting hit far more than average and replicating that one key across multiple cache nodes, spreading its load instead of hammering one. Naming this as distinct from "just add more cache" is the detail that shows depth.

Caching Layer →

Failure & Consistency

What happens if the Key Generation Service goes down?

Say it plainly: it becomes a hard dependency, and new link creation stalls until it recovers, since the write path can't get a guaranteed-unique code without it. That's a real cost of the pre-generated-pool design worth naming rather than hiding — the honest mitigation is running it as a small, highly-available service with a healthy buffer of pre-generated keys, so a brief outage doesn't immediately translate into an outage for link creation.

Key Generation Service →
How do you keep the cache from serving a deleted or edited link?

Two honest answers, and naming both shows range: explicit invalidation (delete the cache key the moment the link is deleted or updated) closes the gap fastest but can be missed; a TTL on every cached entry means even a missed invalidation self-heals within one TTL window. Using both together — invalidate proactively, TTL as a safety net — is the answer that acknowledges invalidation can fail.

Caching Layer →
How would you support link expiration (TTL)?

Add an optional expires_at column to the link record, checked at redirect time before returning the 302 — an expired link returns 410 Gone or a "this link has expired" page instead. The more interesting follow-up is cleanup: rather than scanning the whole table for expired rows, a background job can sweep on a schedule, or you let it expire lazily (checked only when someone actually clicks it) and skip proactive cleanup entirely for anything rarely accessed.

Operating the System

How do you prevent someone from generating millions of spam or phishing links?

The key move is treating link creation and redirection as different risk profiles — creation gets a strict per-account token bucket since legitimate usage is naturally low-volume, while redirects can't be limited the same way since one popular link can legitimately produce huge volume. On top of the bucket, a sliding-window pattern detector ("500 links created in 10 seconds, all pointing at similar domains") catches abuse that stays technically under the numeric limit.

Rate Limiting & Abuse Prevention →
What would you monitor, and what would page someone?

Split it the same way as the design: redirect-path latency and cache hit rate (since that's the user-facing hot path), key-generation pool depletion rate (a leading indicator before link creation actually stalls), and click-event queue lag (a growing lag means analytics are falling behind, even if redirects themselves are fine). Naming queue lag specifically — not just "queue is up or down" — is what shows you understand the async design you just described.

If you had another week, what would you build next?

Point at the design's current weakest assumption rather than a random feature. A strong answer names something already flagged in this guide: hot-key cache replication for a viral link, edge/CDN-level redirects for global latency, or real per-tenant isolation for custom domains rather than shared rate limits. It shows you know where your own design is still thin.