Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for NGINX By James Joyner IV · · 11 min read

AI-Assisted Blue-Green Deployments with NGINX Upstreams

Run blue-green deployments behind NGINX using AI to draft the upstream switch: split_clients canary weighting, a clean cutover, instant rollback, and validating the active color.

  • #nginx
  • #ai
  • #blue-green
  • #deployment

The appeal of blue-green is simple: you run two identical environments, send live traffic to one, deploy to the other, and flip. If the flip goes wrong, you flip back in seconds. NGINX makes a perfectly good blue-green router if you treat the upstream as the switch, and AI is handy for drafting the split_clients weighting and the cutover mechanics. But the part that matters — knowing which color is live and proving the cutover actually moved traffic — is yours, because a blue-green setup that lies to you about the active color is worse than no automation at all.

This guide covers running blue-green with NGINX upstreams, with AI drafting and you verifying.

The two environments

Blue-green assumes two parallel deployments of the same app, each reachable on its own address. Call them blue (127.0.0.1:8081) and green (127.0.0.1:8082). At any moment, one is live and one is idle-or-staging. The goal is to route 100% of production traffic to the live color, deploy and smoke-test the idle one, then cut over.

The cleanest NGINX expression of “which color is live” is a single upstream you re-point, kept in its own include file so the switch is one small, reviewable change rather than an edit threaded through your whole config.

Drafting the upstream switch

I ask AI to set up the structure with the active color isolated:

Draft an NGINX setup for blue-green: two backends, blue on 127.0.0.1:8081 and green on 127.0.0.1:8082. Define a single upstream “app” that I can point at either color by editing one include file. Show the server block that proxies to it and adds an X-Served-By header so I can see which color answered. Output config only.

The result, organized into two files:

# /etc/nginx/conf.d/active-color.conf  -- the ONLY file you edit to switch
upstream app {
    server 127.0.0.1:8081;   # blue is live
    # server 127.0.0.1:8082; # green standby
    keepalive 32;
}
# the server block references the upstream by name
server {
    listen 443 ssl;
    server_name app.example.com;

    ssl_certificate     /etc/ssl/certs/app.example.com.pem;
    ssl_certificate_key /etc/ssl/private/app.example.com.key;

    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # Surface the live color in the response for verification
        add_header X-Served-By $upstream_addr always;
    }
}

The cutover is now a one-line edit to active-color.conf (comment blue, uncomment green) followed by validate-and-reload. Keeping that switch in its own file is the detail that makes rollback trivial: you revert one include and reload. The X-Served-By header is the detail that makes the whole thing verifiable, which I’ll come back to.

Canary first with split_clients

A hard 0-to-100% cutover is risky for anything with real traffic. NGINX’s split_clients lets you send a slice to green first, watch your error rate, then widen it. I prompt for it explicitly:

Add an NGINX split_clients block that sends 10% of traffic to a green upstream and 90% to blue, keyed on the client so a given user sticks to one color. Show how to change the percentage. Output config only.

# Sticky per-client split: 10% green, 90% blue
split_clients "${remote_addr}" $app_pool {
    10%     green_pool;
    *       blue_pool;
}

upstream blue_pool  { server 127.0.0.1:8081; keepalive 32; }
upstream green_pool { server 127.0.0.1:8082; keepalive 32; }

server {
    location / {
        proxy_pass http://$app_pool;
        add_header X-Served-By $app_pool always;
        # ... standard proxy headers
    }
}

Keying on $remote_addr gives a given client a stable color, so users don’t flip-flop between versions mid-session. To widen the canary you bump 10% to 25%, 50%, then retire the split and point the single app upstream at green. AI drafts this correctly, but I always double-check the key — a draft keyed on $request_id would re-roll the dice every request and shatter session stickiness, which is a subtle bug you’d only notice from confused user reports.

Validate, then prove the cutover moved

Every switch goes through the gate:

sudo nginx -t
sudo nginx -s reload

nginx -t confirms the edited include is valid. It does not confirm that traffic actually moved to the color you intended — and that’s the only thing that matters during a deploy. So I prove it with the header I added:

# After cutover, confirm responses come from the new color
for i in $(seq 1 10); do
  curl -s -o /dev/null -D - https://app.example.com/ | grep -i x-served-by
done
# All ten should show the new color's address (or ~10% during a canary)

If you cut over to green and still see blue’s address in X-Served-By, the reload didn’t take or you edited the wrong file — and you’ve just learned that before your users did. That header turns “I think it switched” into “I can see it switched.”

Rollback is the whole point

The reason to build it this way is the rollback. If green starts throwing errors after cutover, you don’t redeploy or debug under fire — you revert the one-line edit in active-color.conf and reload:

# Put blue back live, then:
sudo nginx -t && sudo nginx -s reload

Because the reload is graceful, in-flight requests on green drain rather than getting cut off, and new requests land on blue within seconds. A blue-green setup that can’t roll back this fast isn’t really blue-green; it’s just two environments and hope.

Where AI fits

AI drafted the upstream structure, the split_clients block, and the verification header cleanly. What it didn’t decide for me was the canary keying that preserves stickiness, or the discipline of isolating the switch into one include so rollback stays trivial — and it certainly didn’t watch the X-Served-By header to confirm the cutover landed. Those are the parts that make blue-green safe instead of theatrical. Draft with AI, validate with nginx -t, and verify the active color yourself before and after every flip.

More patterns are in the AI for NGINX category, the upstream health checks and load balancing prompt pairs naturally since blue-green leans on upstream behavior, and the prompt library has the reverse-proxy building blocks underneath all of this.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.