To wire up loose Python microservices, use NATS
JetStream as the message bus with the nats-py
client. JetStream gives you durable consumers, full stream replay, and exactly-once delivery through message dedup and double-ack. It does this in sub-millisecond time, with one small server binary. No Kafka brokers, no ZooKeeper.
This guide covers JetStream setup, pub/sub with durable consumers, a three-service order pipeline, and the steps to harden it for production.
Deploy Prometheus
to scrape metrics from node_exporter
on each Linux server. Then chart it all in Grafana
with CPU, memory, disk, network, and systemd service health. The full stack (Prometheus 3.x, node_exporter 1.10, Grafana 11.6) can watch a 10-server homelab on one Raspberry Pi 4 or a small VM with 1GB RAM. The community Node Exporter Full dashboard (Grafana ID 1860) gives you production-grade views in under 30 minutes.
I’ll show you how to build a real URL shortener in under 200 lines of Python. We’re going to use FastAPI for the web layer, SQLite
for storage, and base62 encoding for short codes. I’ll walk you through a redirect endpoint, a click counter, and rate limiting with SlowAPI
. In my experience, this simple stack handles millions of links on one server.
Key Takeaways
Build a production-ready URL shortener with fewer than 200 lines of Python.
Use SQLite for zero-config storage that handles thousands of requests per second.
Implement base62 encoding to turn database IDs into short, clean strings.
Protect your service with SlowAPI rate limiting to block spam bots.
Deploy the entire app in a 50 MB Docker container behind a Caddy reverse proxy.
Architecture and Tech Stack Choices
Before I write any code, I want to walk you through why I picked this stack. Picking the wrong stack for a small project either over-engineers it or under-builds it. I’ve seen systems fall over at a few hundred users, and I want to help you avoid that.
Yes. For many workloads, systemd-nspawn
beats Docker on leanness, simplicity, and host integration. It shines on servers and homelabs where you want isolated environments without daemon overhead. You launch a container with one command, manage it with machinectl, and run it as a systemd service. All the tools already ship with every modern Linux system.
That said, Docker and nspawn solve slightly different problems. Knowing where each one wins makes the choice easy.
Caddy
is the simplest reverse proxy for self-hosted services. It gets and renews TLS certificates from Let’s Encrypt
with zero config. Install the static binary, write a Caddyfile with three lines per service, and Caddy handles HTTPS, HTTP/2, OCSP stapling, and renewal on its own. That replaces hundreds of lines of Nginx config and separate Certbot cron jobs.
If you run even a handful of services on a home server or VPS, a reverse proxy with proper TLS is non-negotiable. Caddy makes this painless, so there’s no excuse to skip it.
Running CI/CD through GitHub Actions or GitLab CI is handy until it isn’t. Free tier minute limits run out fast. Private repos cost more than you’d expect. And if your code is sensitive, you’re sending every push through someone else’s servers. Self-hosting your pipeline sidesteps all of that.
Gitea
is a light, self-hosted Git service. It has added GitHub Actions-compatible workflow support through a piece called act_runner
. The workflow YAML syntax is near-identical to GitHub Actions. So teams who already know that ecosystem can move over with little friction. This guide walks through a complete, production-ready CI/CD stack on Linux using Docker Compose.