Canary deployments on a single VPS with Nginx
Halving release cycles without Kubernetes: weighted upstreams, health checks, and the rollback path that made Friday ships boring.
7 min read
Kubernetes was not the bottleneck
We needed safer releases, not a new cluster. A single VPS running Docker Compose plus Nginx was enough if traffic splitting and rollback were explicit in the proxy layer.
Weighted upstreams in Nginx
Nginx sits in front of two upstream groups: stable (90%) and canary (10%). New containers register on the canary port only after health checks pass. If error rates spike, we flip weights back to 100/0 without redeploying stable.
- GitHub Actions builds and pushes images, then SSH deploys with a compose override for the canary service
- Health endpoint must validate database connectivity, not just return 200
- Release notes tied to image digest so rollback is a known-good tag, not "previous folder on disk"
What changed in the team rhythm
Release cycles dropped from ten days to five because deploy anxiety decreased. Friday ships became routine once rollback was a one-line Nginx config change rather than a manual restore.