Case studies
Short code generation
Three ways to mint unique short codes (hash the URL, count and encode, or hand out random codes) compared by collisions, guessability and coordination.
Every short link needs a code that no other link uses. Codes are short, so collisions and guessability both matter. The usual answer is to encode a number in base62, which packs many possible values into few characters. Seven characters is enough for trillions of links.
Concept
Before you start
- Base62: a way to write numbers with 62 symbols (
0–9,a–z,A–Z) instead of 10. More symbols means fewer characters for the same number.
Length math
| Length | Capacity |
|---|---|
| 6 characters | 62⁶ ≈ 56.8 billion |
| 7 characters | 62⁷ ≈ 3.5 trillion |
Seven characters gives over 500 times the room needed for 6 billion links. Choosing 7 up front means you never have to change public URLs as the data grows.
The big idea
Each code comes from one of three approaches. Each one answers two questions: can two links get the same code, and can someone guess the next one?
| Approach | How it works | Collisions | Guessable? | Coordination |
|---|---|---|---|---|
| Hash the URL | Hash the long URL, base62-encode it, keep 7 characters | Possible, so check and retry | No | A uniqueness check on every create |
| Counter and base62 | Hand out increasing numbers and encode them | None | Yes, unless you shuffle | Lease blocks of numbers |
| Key service | Pre-generate random codes in batches | None, if issued codes are recorded | No | Batches handed out ahead of time |
Hashing gives the same code for the same URL, which helps deduplication. The cost is a uniqueness check on every create.
Counters are the simplest collision-free option. Each app server leases a block of 10,000 numbers, so the coordinator is touched once per 10,000 creates.
Key services produce random codes that are hard to guess, at the cost of an extra component that must record which codes were issued.
Walking through base62
Encoding repeatedly takes the remainder by 62 and divides by 62. Here is the function from the source, with a few values:
const ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
function toBase62(n: bigint): string {
if (n === 0n) return ALPHABET[0]
let out = ""
while (n > 0n) {
out = ALPHABET[Number(n % 62n)] + out
n /= 62n
}
return out.padStart(7, ALPHABET[0])
}
console.log(toBase62(1n), toBase62(125n), toBase62(3_500_000_000_000n))Output:
0000001 0000021 ZCpdjxeFor 125, the steps are 125 % 62 = 1, then 2 % 62 = 2. Reading the remainders from last to first gives 21, and padding makes it 0000021. The counter 3.5 trillion fits in 7 characters.
Common mistakes
- Using the raw counter as the public code. Codes such as
0000001and0000002let anyone walk through other people's links. Shuffle the numbers before encoding. - Checking for a duplicate, then inserting. Two requests can both pass the check. Put a unique constraint on
codeand retry on conflict. - Reusing a leased block after a crash. Record which block each server owns. Never hand out a block that was not acknowledged as used.
- Choosing 6 characters to save space. You gain little and must redesign URLs as the corpus grows.
Check yourself
1. Why is a 7-character base62 code enough for 6 billion links?
Answer: 62⁷ is about 3.5 trillion, roughly 587 times 6 billion.
2. Why shuffle a counter before encoding it?
Answer: Sequential codes can be walked in order, which exposes links that were meant to be private.
Key takeaways
- Base62 turns a number into a short code, and seven characters covers trillions.
- A counter with leased blocks is simple, collision-free and the usual interview pick.
- Hashing the URL gives deduplication but needs a uniqueness check on every create.
- Shuffle or randomize codes when links are meant to stay hard to find.
Further learning
Next, see how clicks get counted without slowing redirects in click counting off the hot path.
Related
Case study: URL shortener
The classic warm-up: ID generation, read-heavy caching, 301 vs 302 redirects, and analytics without slowing the hot path.
Redirect status codes: 301 vs 302
A redirect's status code tells browsers and CDNs whether they may keep the answer, which decides whether your server ever sees the next click.
Idempotency and retries
Making operations safe to retry, with idempotency keys, deduplicating consumers and jittered backoff, so at-least-once delivery never means a double charge.