Service7 min read

Zero-downtime deploys without Kubernetes

Most teams adopt Kubernetes for deploy orchestration they could get from nginx, a load balancer, and a shell script. Here is when k8s is right, when it is not, and what to use instead.

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

Kubernetes adoption is one of the most expensive default decisions in modern engineering. We see teams spend three months setting up clusters for a workload that a 50-line Ansible playbook and an nginx upstream block would handle forever. Here is when k8s is the right answer and what to use when it is not.

When Kubernetes is the right answer

Three signals: you have ten or more distinct services with different runtime requirements; your team has dedicated platform engineers who want to own the platform as a product; you need features that simpler stacks genuinely cannot provide, like custom autoscaling policies or GPU scheduling across heterogeneous hardware. If you have none of those, k8s is a tax.

Blue/green with nginx and Consul

For most services, a simple pattern works: two upstream pools behind nginx, registered in Consul. Deploy by toggling which pool receives traffic. Health checks run every 2 seconds; unhealthy pools drain automatically. The deploy script is 30 lines of bash. The rollback is the same script with a flag. We have run this pattern for services serving millions of requests per minute.

When you do not need a load balancer

For internal services with low traffic, a process supervisor (systemd, supervisord) plus a local socket is fine. You do not need Envoy. You do not need Istio. You need a working deployment.

Health checks that matter

Liveness probes 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? A green health check that cannot actually serve traffic is worse than no health check at all.

Database migrations during deploys

Most schema changes can be made backward-compatible using the expand-contract pattern. 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 require a maintenance window. The honest answer is faster than the clever script.

Rollback that actually rolls back

We make rollback a first-class deployment target, not an afterthought. The rollback script does the same thing the deploy script does, just with the previous artifact. We test it on every release by rolling back once before marking the deploy successful. A team that has never rolled back in production will roll back badly the first time they need to.

Canary releases on a budget

You do not need Spinnaker or Argo Rollouts to canary. Send 10% of traffic to the new version via the load balancer, watch the metrics, and promote. 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.

FAQ

How do we deploy databases without downtime?

Most schema changes are backward-compatible if you follow the expand-contract pattern: add the new column nullable, deploy code that writes both, backfill, deploy code that reads the new column, drop the old. Truly breaking changes need a maintenance window, and the answer there is honesty, not a clever script.

When is Kubernetes actually worth it?

When you have ten or more services with different runtime requirements, when your team has dedicated platform engineers, or when you need features like custom autoscaling policies that the simpler stacks do not provide. For a single backend with a handful of workers, k8s is a 200% cost overhead and a maintainability tax.

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]