Blue-Green Deployments for Teams Without a Platform Engineer
Blue-green deployments do not require Kubernetes, a service mesh, or a dedicated platform team. Here is a working setup using nothing more than a reverse proxy, two ports, and a shell script.
The phrase “blue-green deployment” conjures images of Kubernetes Ingress controllers, weighted traffic splitting in Istio, and a platform engineer who owns the rollout pipeline. That version exists, and it works well at scale, but it is not the only version. A blue-green deployment is fundamentally two copies of your application running side by side — one serving traffic, one waiting — and a switch that flips which one is active. You can build the whole thing with nothing more than Nginx, two ports, and a script that health-checks a container before cutting over.
For a team of three developers running production on a handful of VPS instances, the heavyweight approach costs more in tooling complexity than it saves in deployment safety. The lightweight version costs a few hours of setup and earns back every minute you would have spent rolling back a bad deploy at 11 p.m.
What blue-green actually does (and does not do)
Blue-green is not zero-downtime deployment. It is near-zero-downtime deployment. The switch from blue to green takes however long your reverse proxy takes to reload its configuration — typically under a second, but not zero. If your application has in-flight requests that span several seconds, the ones that started on blue will fail when blue shuts down unless you drain connections properly. The switch is fast, but it is not atomic.
Blue-green also does not handle database migrations. If your green deployment runs migrations that alter a table schema, the still-running blue deployment will break because it cannot read the new schema. You either need to run backward-compatible migrations (additive only, no renames, no drops) or accept that blue will throw errors for the few seconds between migration and shutdown. The latter is usually acceptable for internal tools and low-traffic apps. For a payments API, it is not.
What blue-green does well is give you a fully validated, production-warm copy of your application before you switch traffic to it. You run health checks against the green instance, smoke-test a few endpoints, and only then cut over. If green fails health checks, traffic stays on blue. The rollback is instantaneous because blue never stopped running.
The manual version that costs nothing
Here is the simplest possible blue-green setup on a single VPS. You run two copies of your application, one on port 3000 (blue), one on port 3001 (green). Nginx sits in front, proxying to whichever port is marked active.
Step one: a config file that tracks the active port.
# /etc/app/active-port
3000
Step two: a deployment script that does the following, in order:
#!/bin/bash
set -e
CURRENT=$(cat /etc/app/active-port)
if [ "$CURRENT" = "3000" ]; then
NEXT=3001
else
NEXT=3000
fi
# Start the new instance on the inactive port
docker compose -p app-"$NEXT" up -d --build
# Health check loop — up to 30 seconds
for i in $(seq 1 30); do
if curl -sf http://localhost:"$NEXT"/health; then
break
fi
sleep 1
done
# Switch Nginx to the new port
sed -i "s/proxy_pass http:\/\/127.0.0.1:$CURRENT/proxy_pass http:\/\/127.0.0.1:$NEXT/" /etc/nginx/sites-enabled/app
nginx -s reload
# Update the active port marker
echo "$NEXT" > /etc/app/active-port
# Drain old instance (wait for in-flight requests to finish)
sleep 5
# Stop old instance
docker compose -p app-"$CURRENT" down
That is under 30 lines of shell. No Kubernetes, no service mesh, no separate staging environment. It handles health checks, traffic switching, connection draining, and cleanup. The only external dependency is Docker and Nginx.
The mid-weight version with a reverse proxy that reloads gracefully
If your application has WebSocket connections or long-lived requests that Nginx’s proxy_pass switch will sever, you need a reverse proxy that can drain connections before switching. HAProxy and Caddy both handle this better than Nginx does out of the box.
HAProxy supports a drain state for backends: when you mark a server as draining, it stops sending new connections to it but keeps existing connections alive until they finish naturally. The deployment flow becomes:
- Start the green instance.
- Health check green.
- Mark the blue backend as draining in HAProxy.
- Wait for in-flight connections to drop to zero (HAProxy exposes this as a metric).
- Add the green backend and remove blue entirely.
This preserves WebSocket sessions through the deployment and avoids the connection-reset errors that Nginx’s reload causes. The cost is that HAProxy’s configuration language is less familiar to most developers than Nginx’s, and the draining step adds 10 to 30 seconds to each deployment cycle. For an app where users stay connected for minutes at a time, the trade is worthwhile.
When to add tooling (and when not to)
If your team already runs Kubernetes, use its native rollout mechanisms. Kubernetes Deployments with strategy: RollingUpdate and readinessProbe give you blue-green semantics without the manual scripting. The tooling is already paid for.
If you are on a platform that handles this for you — Fly.io, Railway, Render — let the platform do it. Fly’s fly deploy spins up a new VM, health-checks it, and switches traffic atomically. Railway does the same with its deployment pipeline. The labor cost of building your own is higher than the platform markup, and the platform has already debugged the edge cases you have not hit yet.
If you are on bare VPS instances and do not want Kubernetes, the 30-line shell script above works. It will not scale to 50 services across 12 machines, but a team of three with three services does not need that scale. The right amount of tooling is the smallest amount that prevents a bad deploy from waking someone up.
FAQ
Do I need two separate databases for blue-green?
What is the difference between blue-green and rolling deployments?
How do I handle static assets during a blue-green deploy?
Related tools
Beehiiv
Newsletter platform with built-in ad network and Boost referrals.
Try Beehiiv →
Webflow
Visual site builder with real CSS export and a CMS that scales.
Try Webflow →
Some links above are affiliate links. We may earn a commission if you sign up. See our disclosure for details.
Related reading
2026-07-20
CDN Edge Caching Explained for Application Developers
Edge caching is not just for static assets. A properly configured CDN can serve API responses, authenticated content, and even dynamic pages from a point-of-presence 20 milliseconds from your user — if you get the Cache-Control headers right.
2026-07-20
Database Backup Strategies That Actually Pass a Disaster Drill
Most backup scripts succeed at creating files and fail at restoring them. Here is how to build a backup pipeline that survives an actual disaster drill — scheduled restores, WAL archiving, and the three things your backup must prove it can do.
2026-07-20
Infrastructure as Code for Solo Founders
You do not need a Terraform monorepo, a dedicated infrastructure engineer, or a complex CI pipeline to get the benefits of infrastructure as code. A single main.tf file, a state backend, and a GitHub Actions workflow that runs on push is enough.
2026-07-20
When Serverless Becomes More Expensive Than a VPS
Serverless pricing lowers the barrier to launch, but above a certain traffic volume, per-request billing flips from saving you money to costing you multiples of a $6 VPS. Here is the crossover math.
2026-06-22
Caddy vs Nginx in 2026: When Automatic HTTPS Is Worth the Switch
A practical comparison of Caddy and Nginx for solo developers and small teams: certificate management, performance trade-offs, config ergonomics, and when switching actually pays off.
Get the best tools, weekly
One email every Friday. No spam, unsubscribe anytime.