The Hidden HTTPS Bug Behind Load Balancers
The subtle HTTPS bug behind mixed content errors, broken redirects, and failed OAuth flows.
Why Your App Breaks Behind a Load Balancer

You deploy your app.
HTTPS is enabled. The SSL certificate works. Everything looks perfect.
Then suddenly:
“Mixed Content: The page at ‘https://yourdomain.com' was loaded over HTTPS, but requested an insecure resource ‘http://yourdomain.com/api/...' This request has been blocked.”
Or you get a redirect loop. Or your API calls silently fail.
You check your load balancer — HTTPS is configured correctly. You check Nginx — it’s running. You check your backend — it’s healthy.
So what went wrong?

The issue usually isn’t your load balancer. It isn’t Nginx either.
Your backend simply doesn’t know the original request was HTTPS.
The Architecture Most Apps Use
Browser → HTTPS → Load Balancer
↓ HTTP
Nginx / Proxy
↓ HTTP
Backend
This setup is called SSL termination.
The load balancer handles HTTPS, while internal traffic stays on HTTP inside a private network.
This is completely normal in production.
Why Mixed Content Happens
Your browser sends:
https://yourapp.com
The load balancer forwards it internally as HTTP.
Now your backend thinks:
"This is an HTTP request"
So when it generates redirects or absolute URLs, it returns:
http://yourapp.com/login
The browser blocks it because the original page was loaded over HTTPS.
That’s the entire bug.
The Wrong Fix
Many engineers solve this by enabling HTTPS everywhere internally too:
Browser → HTTPS → Load Balancer → HTTPS → Nginx
It works.
But now you manage certificates in two places and add unnecessary TLS overhead internally.
You fixed the symptom, not the root cause.
The Real Fix: X-Forwarded-Proto
Load balancers send a header like this:
X-Forwarded-Proto: https
This tells your backend:
“The original client request was HTTPS.”
Nginx
proxy_set_header X-Forwarded-Proto $scheme;
Express / NestJS
app.set('trust proxy', 1)
Django
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
FastAPI
Enable trusted proxy headers so redirects and generated URLs use HTTPS correctly.
Final Architecture
Browser (HTTPS)
↓
Load Balancer
↓
X-Forwarded-Proto: https
↓
Nginx
↓
Backend
Now your backend correctly generates:
https://yourapp.com
No mixed content. No redirect loops. No duplicate TLS setup.
TL;DR
SSL termination at the load balancer is the correct production setup.
Mixed content errors happen because your backend thinks requests are HTTP.
The proper fix is:
- pass
X-Forwarded-Proto - trust proxy headers in your framework
- let the backend know the original request was HTTPS
One header. One configuration. Problem solved.
메타데이터
- post_id
- 32abdce08231
- slug
- the-hidden-https-bug-behind-load-balancers-32abdce08231
- url
- https://medium.com/@samir00/the-hidden-https-bug-behind-load-balancers-32abdce08231
- canonical_url
- https://medium.com/@samir00/the-hidden-https-bug-behind-load-balancers-32abdce08231
- author_url
- https://medium.com/@samir00
- status
- ok
- fetched_at
- 2026-06-09 15:37:30