AB
Backend / Full StackLive & Deployed

Shortly — URL Shortener with Real-Time Analytics

Shortly is a distributed URL shortener built to answer real system design questions — what happens when a link goes viral? How do you count thousands of simultaneous clicks without slowing down redirects? The architecture uses a layered cache-aside pattern where 99% of redirects never touch the database, async click processing via BullMQ so users are never blocked, and Socket.io for live analytics updates.

The Problem

Long URLs are ugly, untrackable, and break in messages — but the real engineering challenge is what happens when a link goes viral. How do you serve thousands of simultaneous redirects without degrading performance, and how do you count every click without ever blocking the user on their way out? Shortly was built to answer those questions with a production-grade architecture, not just a toy shortener.

Key Engineering Decisions

01

Cache-Aside Pattern

Redis sits in front of MongoDB with a 24hr TTL. Deactivating a link evicts the cache immediately — 99% of redirects never touch the database.

02

Async Click Processing

BullMQ decouples click counting from the redirect entirely. Users are never blocked waiting for a write — the queue handles it in the background.

03

Dual Auth Middleware

A single flexAuth middleware tries JWT first, then falls back to API keys — one guard handles both browser sessions and programmatic API access.

04

Distributed Rate Limiting

Redis sliding window shared across all server instances — limits enforced consistently under horizontal scale and persistent across restarts.

05

AI Slug Generation

GPT-4o-mini generates descriptive slugs like 'react-docs-learn' instead of random strings, with automatic fallback when the model is unavailable.

06

TTL Index Expiry

MongoDB TTL indexes auto-delete expired links at the exact timestamp — no cron jobs, no scheduled tasks, no drift.

Key Highlights

  • Cache-aside pattern with Redis — 99% of redirects served in under 1ms, never hitting MongoDB.
  • Async click processing via BullMQ — click counting is fully decoupled from the redirect path.
  • AI slug generation using GPT-4o-mini — turns URLs into memorable slugs like 'react-docs-learn' instead of 'x7km9p'.
  • Dual authentication — JWT for browser sessions, API keys for programmatic access via a single flexAuth middleware.
  • Real-time analytics dashboard powered by Socket.io WebSockets — live click count updates with no page refresh.
  • Redis sliding window rate limiting shared across all server instances, persistent across restarts.
  • MongoDB TTL indexes auto-expire links at exact expiry time — no cron jobs needed.
  • Fully containerized with Docker; frontend on Vercel, backend on Render.

Tech Stack

Node.jsExpressNext.jsTypeScriptMongoDBRedisBullMQSocket.ioDockerOpenAI

Key Takeaways

Decoupling the write path from the read path via an async queue dramatically improves p99 latency — the redirect feels instant even under write pressure.

Cache-aside is simpler than write-through but demands careful invalidation logic; forgetting to evict on deactivation is the exact kind of subtle bug that only shows up in production.

Dual authentication strategies can be cleanly unified in a single middleware by attempting each in sequence — no need for separate routes or duplicated guards.

Redis is not just a cache — using it simultaneously as a cache, rate limiter, and job queue backend is perfectly reasonable and keeps the infrastructure surface area small.

WebSocket connections for the live dashboard need explicit cleanup on disconnect; without it, each abandoned browser tab accumulates a listener on the server.