Django 502 Bad Gateway
Your Django app runs perfectly with runserver, but in production Nginx shows "502 Bad Gateway" on every page, or only on some requests. Users can't reach the site and the error page tells you nothing. A Codersarts Django engineer finds the break between Nginx and your app and gets it serving again.
A 502 Bad Gateway means Nginx couldn't get a valid response from the application server behind it, usually Gunicorn or uWSGI. The most common causes are: the application server isn't running or crashed on startup, Nginx is pointing to the wrong socket or port, Nginx doesn't have permission to access the socket, workers are killed for taking too long, or the server runs out of memory. The Nginx error log almost always names which one it is.
Typical symptoms | 502 on all pages, 502 on slow pages only, errors after a deploy or reboot, intermittent 502s under load |
Most common causes | Gunicorn not running, socket or port mismatch, socket permissions, worker timeouts, out of memory |
How we fix it | Read Nginx and Gunicorn logs, test the app server directly, fix config and startup, tune workers |
Turnaround | Same-day diagnosis; most fixes in 24–48 hours |
Price | Live Debug from $20; fixed-price quote for the full fix |
Signs Your Django App Has a 502 Problem
Every page returns 502 Bad Gateway, but python manage.py runserver works
The site broke after a deploy, a server reboot, or a code change
Nginx error log shows connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)
Nginx error log shows (13: Permission denied) for the socket
Nginx error log shows upstream prematurely closed connection
Only slow pages, reports, or file uploads return 502
Gunicorn logs show WORKER TIMEOUT or workers being restarted
502 errors appear during traffic peaks
Why Django Returns 502 Bad Gateway
In a typical production setup, Nginx receives the request and forwards it to Gunicorn, which runs your Django code. A 502 appears when that handoff fails. The problem is almost never in Nginx itself.
1. Gunicorn isn't running or crashed on startup
If Django fails while loading, Gunicorn can't start. Common triggers are a missing environment variable, a settings error, a failed import after installing new code, a wrong WSGI module path in the service file, or a virtual environment that wasn't activated. With no application server listening, Nginx has nothing to forward to.
2. Nginx points to the wrong socket or port
The address in Nginx's proxy_pass must match exactly where Gunicorn listens. A socket path that changed, a different port, or Gunicorn binding to another interface all break the connection.
3. Socket permission problems
When Gunicorn uses a Unix socket, the user Nginx runs as needs permission to access it and every directory above it. Sockets placed in home directories or created with restrictive permissions produce "Permission denied" errors.
4. Workers killed for timing out
Gunicorn stops workers that take longer than its timeout, which is 30 seconds by default. Slow database queries, large exports, external API calls, or file processing inside a request cause the worker to be killed, and Nginx returns 502 for that request.
5. Out of memory
Too many workers for the server's memory, or requests that load large datasets, can trigger the operating system to kill Gunicorn processes. The result is intermittent 502s that often appear under load.
How We Diagnose the 502
Read the Nginx error log. The exact message separates missing sockets, permission problems, and closed connections.
Check the Gunicorn service. Review service status and logs for startup errors, crashes, and worker timeouts.
Start Gunicorn manually. Run it in the foreground to reveal import, settings, or environment errors.
Test the app server directly. Send a request to the socket or port without Nginx to isolate the failing layer.
Validate Nginx configuration. Confirm proxy_pass matches the Gunicorn bind address and test the config.
Check system resources. Look for memory pressure and processes killed by the operating system.
How We Fix It
Root cause | Fix |
Gunicorn not starting | Fix the settings, import, or environment error, and correct the service file's paths and WSGI module |
Socket or port mismatch | Align Nginx proxy_pass with Gunicorn's bind address |
Socket permissions | Move the socket to a proper runtime directory and set ownership so Nginx can access it |
Worker timeouts | Move slow work to background tasks, optimize slow queries, and set timeouts deliberately |
Out of memory | Right-size worker count, reduce memory-heavy requests, and add swap or resources if needed |
Breaks after reboot or deploy | Make Gunicorn start automatically as a managed service and add a deploy health check |
We confirm the fix by testing normal pages, slow pages, and a restart of the server.
Example Fix
Situation: A Django booking platform on an Ubuntu server returned 502 on every page after the team deployed a new release and rebooted the server.
Cause: The new release read a new environment variable that wasn't in the Gunicorn service file, so Django failed during startup and Gunicorn never created its socket. Separately, the monthly report page regularly exceeded Gunicorn's 30-second timeout.
Fix: Added the environment variable to the service configuration, enabled the service to start on boot, added a post-deploy health check, and moved report generation to a background task with an emailed download link.
Result: The site came back immediately, survived reboots, and the report page stopped causing 502 errors.
How to Keep It From Happening Again
Add a health check after every deploy that fails the release if the app server doesn't respond.
Keep long-running work out of web requests by using a task queue.
Monitor Gunicorn worker restarts and memory so problems show up before users see 502s.
What You Get
Root cause confirmed and explained
Working Nginx and Gunicorn setup that survives restarts
Timeout and worker settings matched to your workload
Deploy health check or monitoring for the same failure
Frequently Asked Questions
What causes a 502 Bad Gateway in Django? Nginx can't get a response from Gunicorn or uWSGI. The app server isn't running, is listening somewhere else, can't be accessed because of socket permissions, or killed a worker because of a timeout or low memory.
Why does my Django site work with runserver but give 502 in production? Runserver doesn't use Nginx or Gunicorn. In production, service configuration, environment variables, socket paths, and permissions all have to be correct for Nginx to reach Django.
What's the difference between a 502 and a 504 error? A 502 means Nginx received no valid response, often because the app server is down or closed the connection. A 504 means Nginx waited too long for a response.
Should I just increase the Gunicorn timeout? Only as a short-term measure. If requests take longer than the timeout, the better fix is optimizing slow code or moving long tasks to a background worker.
Is a 400 Bad Request the same problem? No. A 400 in Django is often caused by ALLOWED_HOSTS not including your domain. That's a Django setting, while a 502 is a connection problem between Nginx and the app server.
Related Problems
Docker container exits immediately
AWS EC2 app not accessible
PostgreSQL queries suddenly slow
Python app memory leak
Next.js build failing on Vercel
Get Your Django Site Serving Again
Share your Nginx error log or the last deploy change. Get a diagnosis and a fixed price.