A URL shortener’s core magic isn’t in the shortening itself, but in how it makes a short, memorable URL instantly point to a potentially massive, complex original URL, and how it does that for millions of users without breaking a sweat.

Let’s spin up a miniature, single-server version to see the gears turn. We’ll use Python and Flask for the web app, and Redis for our super-fast key-value store.

First, the shortening:

from flask import Flask, request, redirect, abort
import redis
import hashlib

app = Flask(__name__)
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)

def generate_short_code(url):
    # Use SHA-256 for a robust hash, then take the first 7 characters
    # This is a simplification; real-world would need collision handling
    return hashlib.sha256(url.encode('utf-8')).hexdigest()[:7]

@app.route('/shorten', methods=['POST'])
def shorten_url():
    original_url = request.form.get('url')
    if not original_url:
        return "No URL provided", 400

    short_code = generate_short_code(original_url)
    # Store the mapping: short_code -> original_url
    redis_client.set(f"url:{short_code}", original_url)
    # Set an expiration for the short URL (e.g., 1 year)
    redis_client.expire(f"url:{short_code}", 365 * 24 * 60 * 60)

    # Construct the full short URL. In production, this would be your domain.
    base_url = "http://localhost:5000"
    return f"Short URL: {base_url}/{short_code}"

if __name__ == '__main__':
    app.run(debug=True)

Now, the redirect mechanism:

@app.route('/<short_code>')
def redirect_to_url(short_code):
    # Retrieve the original URL from Redis
    original_url = redis_client.get(f"url:{short_code}")

    if original_url:
        # Decode from bytes to string
        original_url_str = original_url.decode('utf-8')
        # Optionally, increment a counter for analytics
        redis_client.incr(f"clicks:{short_code}")
        # Return a 301 Permanent Redirect
        return redirect(original_url_str, code=301)
    else:
        # If not found, return a 404
        abort(404)

To test this:

  1. Save the code as app.py.
  2. Make sure you have Flask and Redis installed (pip install Flask redis).
  3. Run Redis server.
  4. Run the app: python app.py.
  5. Open a tool like curl or Postman, and send a POST request to http://localhost:5000/shorten with Content-Type: application/x-www-form-urlencoded and a body like url=https://www.example.com/a/very/long/url/that/needs/shortening.
  6. You’ll get a short URL back, e.g., Short URL: http://localhost:5000/a1b2c3d.
  7. Visit that short URL in your browser, and you’ll be redirected to the original long URL. You’ll also see a click count incremented in Redis if you check redis-cli: GET clicks:a1b2c3d.

The problem this solves is the inefficiency of long, unwieldy URLs. They’re hard to share, remember, and fit into character-limited spaces. A URL shortener provides a clean, concise alias.

Internally, the generate_short_code function is crucial. It takes the original URL and deterministically produces a fixed-length string. This string acts as the primary key. When a user requests the short URL, this key is used to look up the original URL in a fast, in-memory data store like Redis. The server then issues an HTTP redirect (usually a 301 Moved Permanently or 302 Found) to the original URL.

The core levers you control are:

  • Hashing Algorithm: How you generate the short code from the original URL. SHA-256 is good for distribution, but MD5 is faster if collisions are less of a concern for your use case. Base62 encoding of a sequential ID is another common approach, especially for predictable short codes.
  • Short Code Length: Longer codes reduce the probability of collisions but make the short URL slightly less short. 6-7 characters are common.
  • Data Store: The database where you map short codes to original URLs. Redis is excellent for its speed and low latency, perfect for the read-heavy redirect operation. For persistence and larger scale, you might use PostgreSQL or Cassandra.
  • Expiration Policy: How long short URLs remain active. This can be configured per URL or globally.
  • Base URL: The domain name your shortener uses (e.g., bit.ly, tinyurl.com).

The most surprising thing is how little actual "shortening" happens; it’s all a lookup. The short code isn’t derived by removing characters from the original URL; it’s a unique identifier generated from the original URL (or an independent counter) that points to it. This is why you can’t just "unshorten" a URL without knowing the original mapping. The hash function ensures that https://example.com/page1 and https://example.com/page2 will produce different short codes, preventing collisions. If two different long URLs do produce the same short code (a hash collision), a real-world system needs a strategy to handle it, like appending a character or using an alternative hash.

The next hurdle you’ll face is handling massive traffic and ensuring high availability, which brings distributed systems and caching strategies into play.

Want structured learning?

Take the full System Design course →