Engineering7 min read

Zero-downtime deploys when you are not using Kubernetes

Practical patterns for production deploys without k8s: nginx with Consul, blue/green on plain VMs, traffic shifting with HAProxy, and the database migration rules that make any of them safe.

By the RanarTech engineering team · Published 2026-09-22

Zero-downtime deploys are not a Kubernetes feature. They are a discipline. The same patterns work with nginx and a shell script, with HAProxy and a Makefile, with Traefik and a Python script, or with a cloud-native load balancer and a one-liner. The infrastructure is interchangeable; the discipline is not.

Blue/green with nginx and Consul

Two upstream pools behind nginx, registered in Consul with a health check. Deploy to the dormant pool. Run smoke tests against it via a private DNS record. Toggle the load balancer's active pool. Wait for the previous pool to drain. The deploy script is roughly 30 lines of bash; the rollback is the same script with a flag.

Health checks that catch real failures

Health checks that return 200 if the process is alive are noise. Health checks must check what the service actually does: can it reach its database, can it authenticate to its dependencies, can it serve a representative request end-to-end within the latency budget. A green health check that cannot serve traffic is worse than no health check at all.

The database migration discipline

Most zero-downtime deploy disasters trace back to schema changes deployed simultaneously with application changes. The discipline: schema changes use the expand-contract pattern across multiple deploys. Add the new column nullable, deploy code that writes both, backfill, deploy code that reads the new column, drop the old column later. Truly breaking changes need a maintenance window, and the answer is honesty, not a clever script.

Rollback that actually rolls back

We make rollback a first-class deployment target, not an afterthought. The rollback script does exactly what the deploy script does, with the previous artifact. We test rollback on every release by rolling back once before marking the deploy successful. Teams that have never rolled back will roll back badly the first time they need to.

Canary on a budget

You do not need Spinnaker to canary. Send 10% of traffic to the new version via the load balancer, watch the metrics, and promote when they look healthy. The trick is to make the routing change a single command and the metric watch a single dashboard. If your canary takes more than 30 minutes to set up, you will not do it.

Feature flags are deploy infrastructure

Flags decouple deploy from release. We deploy dark code behind a flag, then turn the flag on for a cohort. The flag is a piece of infrastructure; it belongs in your service's config, not in your marketing team's spreadsheet. We use LaunchDarkly, Unleash, or a homegrown 50-line service. What matters is that flag state is consistent across instances and audit-logged.

FAQ

Can we do blue/green without a load balancer?

Yes, by toggling DNS or by using a process supervisor that can drain traffic. Both are more painful than using a load balancer, but they work for low-traffic services where the simplicity is worth it.

What is the single biggest mistake teams make with zero-downtime deploys?

Trying to deploy a database schema change at the same time as an application change. Schema changes must use the expand-contract pattern across multiple deploys. Mixing them in one deploy is the most common source of incidents.

More from RanarTech Insights

Have a project like this?

Discovery call within 48 hours. NDA-friendly. Most engagements kick off within 1-2 weeks.

[email protected]