The feature is a 302 and a lookup, and the plan already includes a user dashboard. This project cuts through overcomplicated backend tutorial bloat by focusing on tangible, testable rules instead of abstract architecture first, so you can ship a working version in a single coding session. The unique deliverable you’ll build is a single reference card with your redirect data table schema, collision handling rules, and expiry logic you can reference while coding without switching between dozens of documentation tabs.
Build Next Stack editors

Single-Page Project Reference Card (Your Core Deliverable)
| Section | Rule Set | Implementation Note |
|---|---|---|
| Redirect Table Schema | Mandatory columns: `short_code` (7-char alphanumeric, unique, primary key), `target_url` (text, non-null), `created_at` (integer Unix timestamp, non-null) | Add `user_id` and `expires_at` as optional columns for later dashboard and expiry features |
| Collision Handling | Generate random 7-char string for each new submission; check for existing `short_code` match before saving; retry up to 3 times if collision is detected | Throw 503 temporary error if 3 consecutive collisions occur, log event for debugging |
| Expiry Logic | Skip all expiry code until 20 valid, testable redirect entries exist in your database | Default to no expiry for user-created entries; add optional TTL selection for users after core flow works |
Store shape for code, target, and created-at
You don’t need a fancy distributed database or complex ORM setup for your first version of this project. Start with a local SQLite instance, which requires zero server setup and works with every common backend language including Node.js, Python, Go, and Ruby. The three mandatory columns in your reference card cover every core requirement for the shortener to work: the `short_code` is the path users will visit on your domain, the `target_url` is the destination they will be sent to, and `created_at` lets you sort entries for your dashboard and run pruning logic later. You can add optional columns later, like a click count to track how many times a short link is used, or a `user_id` to associate links with registered users for the dashboard, but avoid adding any extra columns until your core redirect flow works 100% of the time. Example measurement: A SQLite table with 10,000 short link entries will take up less than 1MB of disk space, so you won’t hit storage limits during local testing for months.
Collision rule when two hashes match
A collision occurs when your code generates a `short_code` that already exists in your database, which would cause two different target URLs to attempt to use the same short path. Many new developers make the mistake of hashing the target URL to generate the short code, which causes predictable collisions if two users submit the same URL, and also makes it easy for bad actors to enumerate all existing short codes on your platform. The rule in your reference card avoids this by using random string generation instead of hashing, which makes collisions extremely rare: with 7 alphanumeric characters, there are 36^7, or roughly 78 billion, possible unique codes. Even if your demo reaches 100,000 entries, the probability of a collision is less than 0.1%. When you do encounter a collision, retry generation up to 3 times before throwing an error, as repeated consecutive collisions are almost always a sign of a bug in your random string generation code rather than a legitimate statistical event. This collision handling logic is a small addition that teaches you defensive coding practices you’ll use for every distributed system project you build later.
Redirect you can test with curl -I
The core functionality of your shortener lives in the redirect route, which runs every time a user visits a path on your domain that matches a `short_code` format. The rule here is simple: when a GET request hits `/[short_code]`, query your database for a matching entry. If the entry exists, return a 302 Found status code with a `Location` header set to the `target_url` value. If no matching entry exists, return a 404 Not Found status code with a generic error page that links back to your homepage. You can test this functionality in 10 seconds with curl, no browser required, by running the command `curl -I http://localhost:3000/[your-test-code]`. The `-I` flag tells curl to only fetch response headers, so you don’t have to follow the redirect to confirm it works. A successful test will return output that includes `HTTP/1.1 302 Found` and `Location: https://your-target-url.com`. Avoid using a 301 Moved Permanently status code for your redirects, as 301s are cached by browsers indefinitely, which means if you update the target of a short code later, returning users will still be sent to the old URL until they clear their browser cache.

Expiry you skip until the table has 20 rows
It’s tempting to add expiry logic, auto-pruning, and TTL selection for users before you’ve confirmed your core redirect flow works, but that’s a common mistake that delays shipping a working version of your project. The rule in your reference card requires you to skip all expiry-related code until you have 20 valid, testable entries in your redirect table that you can confirm work with curl, show up correctly in your user dashboard, and don’t have any collision or lookup bugs. Once you hit that 20 row threshold, add an optional `expires_at` column to your table that defaults to null (meaning the link never expires) unless the user selects a specific expiry window when creating the link. You can then add a simple scheduled job that runs once per day to delete any entries where `expires_at` is not null and the timestamp is earlier than the current time. Illustrative example: You can test your expiry logic by creating a test link set to expire 5 minutes after creation, then running your pruning script manually to confirm the entry is removed from the database and requests to that short code return a 404 error.
Public demo that never stores a secret URL
Once your local version works, you can deploy it to a public host like Render, Fly.io, or Vercel to share with other learners, but you need to add basic safety rules to prevent abuse. First, add a simple content filter that blocks submissions of URLs containing sensitive keywords like login, password, banking, crypto, or admin, to prevent users from sharing sensitive or malicious links through your demo. Second, set a default 30-day expiry for all links created on the public demo, with no option for permanent links, so you don’t end up storing thousands of unused or spam links indefinitely. Third, add a reporting link on your 404 page so users can report spam, phishing, or malicious links, and set a reminder to check these reports once per week to prune bad entries. You should also include a clear disclaimer on your homepage stating that the demo is for learning purposes only, you do not monitor or endorse the content of redirected links, and users should not submit any sensitive or private URLs to the public demo.
Open your code editor right now, create the core redirect table as outlined in your reference card, generate your first 3 test short codes, and confirm they redirect correctly with curl before adding any extra dashboard or user functionality.