Back to Projects
Snipp

Snipp

A URL shortener built as a full system-design exercise — requirements and capacity estimation written before any code, then a Redis cache layer, rate limiting and click analytics measured against those numbers.

Aug 2026 - Present Less than a month Ongoing

Tech Stack

TypeScriptNode.jsExpressNext.jsReactPrismaMySQLRedisNginxPM2

Features

The central design point

Snipp looks like a CRUD app, but it has two data paths with completely different characteristics:

Write path (create)Read path (redirect)
Traffic~0.4 req/s~39 req/s (100×)
Latency budget300ms (p95)50ms (p99)
CacheNoneRedis is the primary path

So the redirect path doesn’t go through Next.js at all — both share one domain, split by path at the edge.

Benchmark

Redirect path, 50 connections, autocannon, dev machine — the value is in the ratios, not the absolute numbers.

Statereq/sp99clicks recorded
no-cache (baseline)74836ms100%
cache-only2,24135ms3%
cache-hit (real traffic)3,28244ms100%

The interesting row is cache-only: latency looked nearly perfect while 97% of clicks silently vanished. Caching the read path removed the connection-pool contention that had been acting as accidental backpressure, so MySQL got ~4,500 writes/s it couldn’t absorb — and since clicks are fire-and-forget, nothing surfaced. Removing a bottleneck without replacing it turns a latency problem into a data-loss problem.

Decisions worth naming

Capacity estimation changed the design

The clicks table works out to 97% of storage — ~240 GB/year, forty times the links table. So raw clicks are kept 90 days, and the dashboard queries an aggregate table rather than ever running COUNT(*) over raw rows.

View All Projects
My Projects About Me