Staging vs Production Header Differences — How to Find What Is Missing

Updated April 2026

Security headers you carefully configured in staging often disappear in production — stripped by a CDN, load balancer, or reverse proxy. Here is how to find the exact difference in 30 seconds.

Why headers differ between environments

Your app server sets the headers. But in production, the response passes through layers that can modify or strip them:

The fastest way to find differences

Paste both URLs into Header Diff and it highlights every difference automatically — missing headers in red, value changes in orange, additions in green.

Compare headers between two URLs → Header Diff

Using curl to compare manually

# Staging
curl -sI https://staging.yourapp.com | sort > staging-headers.txt

# Production
curl -sI https://yourapp.com | sort > prod-headers.txt

# Diff
diff staging-headers.txt prod-headers.txt

The most commonly dropped headers

HeaderWhy it gets droppedFix
Content-Security-PolicyCDN strips large headers, or proxy_pass doesn't forwardSet at CDN layer (Transform Rules) not just origin
Strict-Transport-SecurityLoad balancer terminates SSL, strips HSTSSet on the load balancer / CDN, not the backend
X-Frame-OptionsNginx proxy_pass without add_header in server blockMove add_header to the server{} block, not location{}
Permissions-PolicyRelatively new, often missed in CDN configsAdd via Transform Rules or response header policy

Common Nginx mistake

In Nginx, add_header in a location{} block does not inherit from the parent server{} block. If you have add_header in any nested location, you must repeat all headers in that location:

# Wrong — CSP will be dropped in /api/ responses
server { add_header Content-Security-Policy "default-src 'self'"; location /api/ { add_header X-Custom "value";  # This wipes the CSP header proxy_pass http://backend; }
}

# Correct — repeat all headers
server { location /api/ { add_header Content-Security-Policy "default-src 'self'" always; add_header X-Custom "value" always; proxy_pass http://backend; }
}

Cloudflare stripping headers

If your origin sets security headers but Cloudflare strips them, set them in Cloudflare Rules → Transform Rules → Modify Response Header instead of relying on origin pass-through. This ensures headers are set at the edge regardless of origin behaviour.

Pre-deployment checklist