Gen-Endpoint
Back to Blog

How to Build and Test URL Shortener Features in Modern Web Applications

By Kunal Burangi•Published on November 1, 2026•
System Design & Prototyping
#URL Shortener
#System Design
#QR Code
#Analytics
#Web Development

How to Build and Test URL Shortener Features in Modern Web Applications

URL shorteners like Bitly, TinyURL, and Dub appear deceptively simple on the surface: a user enters a long destination URL, and the server returns a compact link like https://gen-endpoint.com/s/7xK9.

However, under the hood, URL shorteners encompass critical software engineering and system design concepts: Base62 encoding, unique ID generation, hash collision resolution, 301 vs 302 redirection semantics, click analytics pipelines, and dynamic QR code generation.

In this comprehensive guide, we dissect how URL shorteners work, analyze why choosing the wrong HTTP redirect status code destroys click tracking, explore database architecture and caching strategies, and demonstrate how to test shortening workflows using Gen-Endpoint's URL Shortener API and QR Code Generator API.


1. System Design: How Short Codes Are Generated

How does a server transform https://example.com/very/long/deep/link?utm_source=twitter into a 6-character slug like 8fKm2Q?

The Base62 Encoding Strategy

The standard alphabet for short URLs uses Base62, containing:

  • 26 lowercase letters (a-z)
  • 26 uppercase letters (A-Z)
  • 10 digits (0-9)
  • Total = $26 + 26 + 10 = 62$ characters.

With a 6-character Base62 string, you can generate: $$62^6 = 56,800,235,584 \text{ unique short links!}$$

Over 56 billion links without a collision!

// utils/base62.ts
const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

export function encodeBase62(num: number): string {
  if (num === 0) return ALPHABET[0];
  let result = '';
  let n = num;
  while (n > 0) {
    result = ALPHABET[n % 62] + result;
    n = Math.floor(n / 62);
  }
  return result;
}

export function decodeBase62(str: string): number {
  let num = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str[i];
    const index = ALPHABET.indexOf(char);
    if (index === -1) throw new Error(`Invalid Base62 character: ${char}`);
    num = num * 62 + index;
  }
  return num;
}

2. 301 vs. 302 vs. 307 Redirect Semantics

When a user visits a shortened link, the server responds with an HTTP redirection header. Selecting the correct status code is critical:

| HTTP Status Code | Browser Caching Behavior | Impact on Analytics Telemetry | Recommended Use Case | | :--- | :--- | :--- | :--- | | 301 Moved Permanently | Browser caches redirect permanently on the user's device | Destroys Analytics! Subsequent visits bypass your server entirely | Canonical domain migrations | | 302 Found | Browser does not cache; contacts server on every request | Full Telemetry: Logs click timestamps, referrers, and geo-data | Legacy shortener standard | | 307 Temporary Redirect | Preserves HTTP method; never caches without explicit header | Modern Standard: 100% accurate click analytics and audit trails | Best for modern shorteners |

Key Rule: Always use 302 Found or 307 Temporary Redirect for URL shorteners to ensure every click contacts your server for click logging.


3. Database Architecture & Sub-5ms Caching Strategy

A URL shortener is a read-heavy system (often 100:1 read-to-write ratio). Direct database queries on every click will saturate database connection pools.

The Two-Tier Storage Architecture:

  1. Primary Database (PostgreSQL / MySQL):
    • urls table: id, short_code (Unique B-Tree Index), original_url, created_at.
    • clicks table (or ClickHouse): id, short_code, referrer, user_agent, ip_hash, country, clicked_at.
  2. In-Memory Cache (Redis):
    • Key: short:{code} $\rightarrow$ Value: original_url with 24-hour TTL.
    • When a user visits /s/abc123, the server checks Redis. On cache hit, it redirects immediately in under 3 milliseconds, pushing the click event to an asynchronous queue (BullMQ or Kafka) for background analytics processing.

4. Testing Shortening with Gen-Endpoint's Live API

Gen-Endpoint provides a live URL Shortener endpoint that validates URLs, creates unique short slugs, and tracks real-time click statistics:

# 1. Shorten a destination link
curl -X POST https://gen-endpoint.com/api/shorten \
  -H "Content-Type: application/json" \
  -d '{"url": "https://github.com/trending"}'

Sample Response:

{
  "shortUrl": "https://gen-endpoint.com/s/gh-trend",
  "shortCode": "gh-trend",
  "originalUrl": "https://github.com/trending",
  "createdAt": "2026-11-01T15:00:00.000Z"
}

You can query real-time analytics for any code:

# 2. Check click statistics
curl https://gen-endpoint.com/api/stats/gh-trend

5. Building an Interactive URL Shortener Component in React

Here is a full React component with URL validation, instant copy-to-clipboard feedback, and dynamic QR code generation:

// components/UrlShortenerWidget.tsx
'use client';

import React, { useState } from 'react';

export function UrlShortenerWidget() {
  const [destinationUrl, setDestinationUrl] = useState('');
  const [shortUrl, setShortUrl] = useState<string | null>(null);
  const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [copied, setCopied] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);
    setCopied(false);

    try {
      new URL(destinationUrl); // Basic client URL validation
    } catch {
      setError('Please enter a valid URL including http:// or https://');
      return;
    }

    setIsLoading(true);

    try {
      const res = await fetch('https://gen-endpoint.com/api/shorten', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url: destinationUrl }),
      });

      if (!res.ok) throw new Error('Shortening failed');

      const data = await res.json();
      setShortUrl(data.shortUrl);
      setQrCodeUrl(`https://gen-endpoint.com/api/qr?text=${encodeURIComponent(data.shortUrl)}&size=200`);
    } catch (err: any) {
      setError(err.message || 'Error shortening link');
    } finally {
      setIsLoading(false);
    }
  };

  const copyToClipboard = () => {
    if (!shortUrl) return;
    navigator.clipboard.writeText(shortUrl);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <div className="max-w-xl mx-auto p-6 bg-card border rounded-2xl shadow-sm space-y-6">
      <div>
        <h3 className="text-xl font-bold tracking-tight">Create Short Link & QR Code</h3>
        <p className="text-sm text-muted-foreground mt-1">
          Generate trackable short URLs and high-resolution QR codes instantly.
        </p>
      </div>

      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <input
            type="url"
            value={destinationUrl}
            onChange={(e) => setDestinationUrl(e.target.value)}
            placeholder="https://yourlongdomain.com/deep/landing/page"
            required
            className="w-full px-4 py-2.5 rounded-xl border bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary"
          />
        </div>

        {error && <p className="text-xs text-destructive">{error}</p>}

        <button
          type="submit"
          disabled={isLoading}
          className="w-full py-2.5 rounded-xl bg-primary text-primary-foreground font-semibold text-sm hover:bg-primary/90 transition-opacity disabled:opacity-50"
        >
          {isLoading ? 'Generating Link...' : 'Shorten URL'}
        </button>
      </form>

      {shortUrl && (
        <div className="p-4 bg-muted/30 border rounded-xl space-y-4">
          <div className="flex items-center justify-between gap-3">
            <span className="text-sm font-semibold text-foreground truncate">{shortUrl}</span>
            <button
              onClick={copyToClipboard}
              className="px-3 py-1.5 text-xs font-medium rounded-lg bg-secondary text-secondary-foreground hover:bg-secondary/80"
            >
              {copied ? 'Copied! ✓' : 'Copy'}
            </button>
          </div>

          {qrCodeUrl && (
            <div className="pt-2 border-t flex flex-col items-center space-y-2">
              <p className="text-xs text-muted-foreground font-medium">Scan QR Code</p>
              <img
                src={qrCodeUrl}
                alt="QR Code for Short URL"
                className="w-36 h-36 rounded-lg border bg-white p-2"
              />
            </div>
          )}
        </div>
      )}
    </div>
  );
}

Summary & Practice

URL shortening involves rich frontend and system design concepts: Base62 encoding, 302/307 redirects, sub-5ms caching, and dynamic QR imagery. By pairing Gen-Endpoint's URL Shortener API with our QR Code API, you can prototype link-management dashboards, analytics graphs, and marketing campaigns in minutes.

Free Developer Tooling

Ready to Test These Endpoints?

Access 23+ free mock REST APIs, test file uploads, and generate Next.js API handlers with zero signup.