Case study
A URL shortener is a small product with a long tail of real concerns: abuse, expiry, accounts, email, and a redirect path that has to stay fast. I built Shorty alone in under two weeks in June 2025 to ship one properly, and it has been live at shorty.ma since, with short links on shrt.ma.
Highlights
- Shortening without an account: a guest's link gets a six-character slug and expires after a set number of days. Signed-in users with a confirmed email keep their links with no expiry.
- A complete account lifecycle: sign-up, email confirmation and resending it, sign-in, refresh, sign-out, forgotten and reset passwords, and changing a password, with emails sent through Brevo.
- Short-lived access tokens, and a refresh token kept in an HTTP-only cookie the page's scripts can't read.
- Rate limits held in Redis and tuned per endpoint: three sign-ups an hour, ten sign-in attempts per ten minutes, and shortening capped at ten a minute and two hundred a day per visitor.
- A dashboard of your links with search, sorting and pagination, click counts and deletion.
- QR codes for any short link, as PNG or SVG at a chosen size, cached in Redis so a popular code is drawn once.
- An async FastAPI backend on PostgreSQL with Alembic migrations, a React and TypeScript frontend served by Nginx, a request id on every response, and errors returned in one predictable shape.
The Redirect Path
The redirect is the one route everyone hits, so it does the least: look up the slug, refuse an expired link with a clear not-found, count the click, and answer with a temporary redirect. Everything else (accounts, listings, QR codes) lives under the versioned API and can be slow without anyone following a link noticing.
Guests And Accounts
Letting anyone shorten a link is the point of the product and its main abuse risk, so the two are balanced with limits rather than sign-up walls. A guest's link works immediately but expires; an account makes links permanent, but only once its email is confirmed, so a throwaway address can't collect permanent links. The limits are tightest where abuse is cheapest: creating accounts and guessing passwords.
QR Codes
Each short link has a QR endpoint that draws the code with segno at the requested size and format. Generated codes are cached in Redis by slug, size and format, so asking for the same code again costs nothing to draw, and the endpoint has its own rate limit.
A Refactor That Didn't Ship
In August 2025 I ran a second pass on both halves toward Clean Architecture (domain, application, infrastructure and presentation layers), spec-first with Kiro, an AI coding agent working from written requirements, designs and task lists. It hasn't shipped: it sits uncommitted in the working tree, and the live site is the June build described above. Its own log declares it production-ready while listing test files that don't parse.
Why This Project Matters
Shorty is a small product taken all the way to production: a domain, real email, accounts, abuse limits and a live service people can use. The parts that look like extras (expiry for guests, confirmed emails before permanence, limits per endpoint) are the parts that keep a free public tool from becoming someone else's spam infrastructure.
