Stop 22 · Build Backend Portfolio ProjectsProjects · 1/14

URL Shortener

Part of the Backend Developer Roadmap

In short

It sounds like a weekend toy, but a good URL shortener touches ID generation, redirects, caching and analytics. Interviewers love asking about it, so building one gives you real stories to tell.

A production version of the classic system-design project — short code generation, redirect handling, and click analytics — a compact but genuinely impressive portfolio piece.

The purple blob swaps a very long paper scroll for a tiny paper tag.

Think of it like this

A PNR for a long train trip

Your train booking has a long list of details: train, coach, berth, date, passengers. But you only need a 10-digit PNR to pull it all up. A short link is the same: a tiny code that stands for a very long URL.

Watch it happen

Create a link, then click it

Browser
API
Redis
Postgres

POST /shorten

1/7The user sends a long URL. The API validates it is a real http or https link.

The big ideas

What you need to know

Short code generation

Base62-encode a database ID, or generate random codes and retry on collision. Know the trade-offs of each.

Fast redirects

The redirect path must be tiny: cache lookup, then 302. Everything else, like analytics, happens after.

Click analytics

Count clicks per link per day. Push click events to a queue so redirects never wait on writes.

Abuse protection

Validate URLs, rate-limit creation and allow links to be disabled, because spammers love shorteners.

See it in code

Walk through the code

ts
1const ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";2 3function toBase62(id: number): string {4  let code = "";5  do {6    code = ALPHABET[id % 62] + code;7    id = Math.floor(id / 62);8  } while (id > 0);9  return code;10}11 12app.get("/:code", async (req, res) => {13  const url = (await redis.get(`url:${req.params.code}`)) ?? (await findInDb(req.params.code));14  if (!url) return res.status(404).send("Link not found");15  res.redirect(302, url); // 302 so every click reaches us and can be counted16});

1/3Repeatedly take the remainder by 62 to pick a character, like converting to a new number base.

Seven base62 characters cover about 3.5 lakh crore IDs. Remember to save cache misses back into Redis with a TTL.

Save yourself the pain

Common mistakes

Oops

Using plain sequential codes like 1, 2, 3 that anyone can guess and scan.

Do this instead

Shuffle IDs (for example with Sqids) or use random codes if links shouldn't be enumerable.

Oops

Writing a click row to the database before every redirect.

Do this instead

Redirect first, then push a click event to a queue or increment a Redis counter and batch-save.

Your mission

Milestone 1: a working shortener

~45 min

Quick check

Why do many shorteners use 302 instead of 301 for redirects?

Go deeper

  1. 1Add click analytics (count, referrer, timestamp) for each shortened link.
  2. 2Cache the redirect lookup path aggressively since it's extremely read-heavy.
  3. 3Add custom aliases and link expiration as bonus features.

More projects at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge