All posts

Fix Load Balancer Error in Flask

Resolve Flask application errors behind a load balancer, covering proxy headers, URL scheme detection, and Gunicorn configuration.

Flask Behind a Load Balancer

Flask doesn't know it's behind a proxy unless you tell it. This leads to wrong url_for() URLs (HTTP instead of HTTPS), broken redirects, and health check failures.

The ProxyFix Middleware

This is the essential fix for Flask behind any reverse proxy:

from werkzeug.middleware.proxy_fix import ProxyFix

app = Flask(__name__)
app.wsgi_app = ProxyFix(
    app.wsgi_app,
    x_for=1,       # X-Forwarded-For
    x_proto=1,     # X-Forwarded-Proto
    x_host=1,      # X-Forwarded-Host
    x_prefix=1     # X-Forwarded-Prefix
)

Without this, request.is_secure returns False and url_for() generates http:// links even when users access the site via HTTPS.

Health Check Route

@app.route('/healthz')
def health():
    return 'ok', 200

Gunicorn Configuration

Flask's development server can't handle production traffic. Use Gunicorn with proper settings:

# gunicorn.conf.py
bind = '0.0.0.0:8000'
workers = 4
worker_class = 'gthread'
threads = 2
timeout = 120
keepalive = 5
forwarded_allow_ips = '*'  # Trust proxy headers

The forwarded_allow_ips setting is critical — without it, Gunicorn strips forwarded headers for security.

Load Balancer Timeout Mismatch

If the ALB timeout exceeds Gunicorn's timeout, you'll get 502 errors when requests take too long:

ALB idle timeout:  60s
Gunicorn timeout: 30s  ← Worker killed, ALB sees a closed connection

Set Gunicorn's timeout higher than the load balancer's. Bugsly flags these 502 patterns by correlating error spikes with request duration, helping you tune timeouts correctly.

Try Bugsly Free

AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.

Get Started Free