URL Shortener System Design

A URL shortener maps a long URL to a short code and redirects on lookup. The design hinges on one decision - how you generate the short code - plus the data model and the redirect path. Here's the whole thing.

Backend Engineerbackendsystem-designurl-shortener

The requirements

The key decision: generating the short code

Scheme Pros Cons
Base62 of an auto-increment id Dense, guaranteed unique, ~6 chars at scale, no collision checks Sequential - leaks growth rate, codes are guessable
Hash of the URL (md5(url)[:n]) Same URL -> same code (free dedup) Collisions at scale need handling
Random string Unguessable Must check the DB for collisions on every insert

Base62 of the row id is the usual default: store the row, take its integer id, encode it base62. Unique by construction - no collision check needed.

ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def base62(n: int) -> str:
    if n == 0:
        return ALPHABET[0]
    s = []
    while n:
        n, r = divmod(n, 62)
        s.append(ALPHABET[r])
    return "".join(reversed(s))

The data model

One table is enough to start:

CREATE TABLE urls (
    id    INTEGER PRIMARY KEY AUTOINCREMENT,  -- the id we base62-encode
    url   TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Insert the URL, read back the id, return base62(id) as the code. On redirect, decode the code back to the id (or just store the code and index it) and look up the URL.

The redirect flow

@app.get("/<code>")
def redirect_code(code):
    row = db.execute("SELECT url FROM urls WHERE code = ?", (code,)).fetchone()
    if not row:
        abort(404)
    return redirect(row["url"], code=301)   # 301 = permanent, cacheable

Use 301 so browsers and CDNs cache the redirect - that's what makes reads cheap.

How it scales

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

How does a URL shortener generate the short code?

The common approach is base62-encoding an auto-increment row id - unique by construction, ~6 chars at scale, no collision checks. Alternatives are hashing the URL (free dedup, but collisions) or random strings (unguessable, but you must check for collisions).

Why use a 301 redirect for a URL shortener?

301 (permanent) lets browsers and CDNs cache the redirect, so most requests never hit your service - which is what keeps a read-heavy shortener fast and cheap. Use 302 only if you need to count every click.

How do you scale a URL shortener?

Cache the code-to-URL lookup (reads vastly outnumber writes), serve redirects through a CDN, and replace the single auto-increment id with a distributed id scheme so writes don't bottleneck on one counter.

Keep learning

Return the Correct HTTP Status CodeBackend projectRepair Broken API PaginationBackend projectAdd CORS Middleware to an Express APIBackend projectBackend roadmapStep by step to hiredBackend interview questionsSTAR answersAll Backend projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →