URL Shortener
A Go URL shortener on a self-hosted Kubernetes homelab, load tested on a single 6-core machine. It handles ~30k clean req/s with a p99 of ~150ms, up from 180 req/s on the first deploy.
At that rate, the bottleneck is the host’s CPU, not the API.
Try itThe live shortener. It goes through Cloudflare and Envoy, not the stripped-down mesh path from the benchmarks.
Source codeThe API, load tests, dashboards and Kubernetes manifests.
Using the API
Section titled “Using the API”Shorten a URL:
curl -X POST https://url-shortener.grncunha.com/v1/url \ -H 'Content-Type: application/json' \ -d '{"longUrl": "https://grncunha.com/blog/system-design-beyond-the-design/"}'The response is the short code:
{"shortUrl":"f484869be0c09ec98780b7762a6f559c"}https://url-shortener.grncunha.com/v1/url/<shortUrl> then redirects (HTTP 302) to the original URL.
- API: Go
- Storage: Postgres, with Redis in front for reads
- Deployment: self-hosted Kubernetes (Talos on Proxmox), one physical server
- Networking: Cilium, a Headscale mesh with WireGuard encryption, and cloudflared for public traffic, with Envoy on the public path only
- Monitoring: Prometheus metrics in Victoria Metrics, Grafana dashboards
- Load testing: k6
Not done yet
Section titled “Not done yet”I’m moving on to other things, so these will probably stay this way:
- Expiry: URLs are meant to expire after 24 hours, but don’t yet
- Click counting: the redirects are temporary (302) so clicks can be counted, but nothing counts them
- Short codes: the code is the full 32-character MD5 hash, so it isn’t actually short
How it got to 30k req/s
Section titled “How it got to 30k req/s”A URL shortener at 30k req/s on a 6-core homelabFrom a first deploy that collapsed to 180 req/s, to ~30k on the same box.