Gunicorn & app servers for Django in production
The WSGI and ASGI servers that run Django: Gunicorn, uWSGI, Uvicorn, Granian, and mod_wsgi, and how their workers fail.
Gunicorn, Uvicorn, uWSGI, and Granian turn Django into a process that serves HTTP. Their settings decide your capacity, memory use, and how slow requests affect everyone else.
The guides cover running them correctly, sizing workers and threads, and fixing the errors they produce: boot failures, timeouts, OOM kills, and address conflicts.
Set it up
Guides that take this from nothing to running in production.
- Deploy Django with uWSGI and Nginx
Run Django with uWSGI and Nginx: a strict uWSGI ini, socket permissions, systemd integration, graceful reloads, harakiri timeouts, and checks.
- Deploy Django with Apache and mod_wsgi
Deploy Django on Apache with mod_wsgi daemon mode, a matching virtualenv, static file aliases, secret loading, HTTPS, and code reloads without restarting Apache.
- Deploy Django with Granian
Run Django in production with Granian, the Rust HTTP server for Python: WSGI and ASGI interfaces, workers and threads, a systemd unit, Nginx in front, and when to choose it.
- Deploy Django on Windows Server With IIS
Deploy Django on Windows Server behind IIS: run Waitress through HttpPlatformHandler instead of the unmaintained wfastcgi, serve static files from IIS, run it under an app pool identity, and add HTTPS with an IIS binding.
- Run Django With Hypercorn
Run Django in production with Hypercorn, an ASGI and WSGI server with HTTP/2 and HTTP/3 support: configure workers and worker class, bind behind Nginx, set timeouts and graceful shutdown, and compare it with Uvicorn and Gunicorn.
- Deploy Django With NGINX Unit
Run Django on NGINX Unit, the application server configured through a JSON API: configure a Python application with a virtualenv, route static files, set processes, add TLS, and check the project's maintenance status before adopting it.
- Write a gunicorn.conf.py for Django
Configure Gunicorn for Django with a gunicorn.conf.py file: bind, workers and threads, timeouts, max_requests with jitter, logging to stdout, forwarded headers, preload trade-offs, and server hooks for database connections.
- Gunicorn vs uWSGI for Django
Compare Gunicorn and uWSGI for serving Django in production: configuration complexity, performance, worker models, features like the uwsgi protocol and emperor mode, maintenance status, and which to choose for new and existing projects.
- Gunicorn vs Uvicorn for Django
Compare Gunicorn and Uvicorn for Django: WSGI versus ASGI, when async views and WebSockets need Uvicorn, running Uvicorn workers under Gunicorn, performance for typical database-bound apps, and how to choose.
- Why You Should Not Use runserver in Production
Why Django’s manage.py runserver is not for production: single-process design, no security review, static file handling, auto-reload, and DEBUG coupling, plus what to run instead with Gunicorn, Uvicorn, and a reverse proxy.
- Deploy Django With mod_wsgi-express
Run Django in production with mod_wsgi-express: install mod_wsgi with pip into the virtualenv, generate a self-contained Apache configuration, serve static files, run it under systemd, and put it behind Nginx or use it directly on port 80.
- Run Django in Production on Windows With Waitress
Run Django on a Windows server with Waitress: install it in a virtualenv, serve the WSGI app on a port, run it as a Windows service with NSSM, put IIS or Caddy in front for HTTPS and static files, and tune threads and logging.
- Django WSGI vs ASGI: Which One Should You Deploy?
When you deploy Django in production, you will see both WSGI and ASGI recommended.
- Deploy Django with Gunicorn and Nginx on Ubuntu
Moving a Django app from local development to production usually fails on the same points: process management, reverse proxy configuration, static files, secrets, TLS, and safe...
- Deploy Django ASGI with Uvicorn and Nginx
If you want to deploy Django ASGI with Uvicorn and Nginx, python manage.py runserver is not a production option.
- How to Configure systemd for Gunicorn and Django
Running Gunicorn manually for a Django app is fragile. If your SSH session closes, the process can stop.
- Deploy Django on cPanel Shared Hosting
Deploy Django on cPanel shared hosting with Setup Python App and Phusion Passenger: create the app and virtualenv, write passenger_wsgi.py, use MySQL or PostgreSQL, serve static files from public_html, and know the hosting limits.
Run it well
Tuning, reliability, and operations once it works.
- How to Optimize Gunicorn Workers for Django
If you want to optimize Gunicorn workers for Django, the main production risk is getting concurrency wrong.
- Use Gunicorn preload_app With Django
Decide whether to enable Gunicorn preload_app for Django: memory savings from copy-on-write, faster worker boot, fail-fast startup, the database and client connections you must close after fork, and why reloads need a full restart.
- Run Gunicorn gevent Workers for I/O-Heavy Django Apps
Use Gunicorn gevent workers for Django apps that spend time waiting on external APIs: worker_connections, monkey patching, psycopg and database connection limits, CPU-bound pitfalls, and comparing gevent with threads and ASGI.
- Reduce Django Startup and Import Time
Make Django processes start faster: measure import time with python -X importtime, defer heavy imports, avoid database queries at import, trim INSTALLED_APPS, and why startup matters for serverless, autoscaling, deploys, and management commands.
- Graceful Shutdown for Django and Celery (SIGTERM)
Shut down Django web servers and Celery workers without dropping requests or tasks: how Gunicorn, Uvicorn, and Celery handle SIGTERM, graceful timeouts, Docker stop_grace_period, Kubernetes preStop and terminationGracePeriodSeconds, and PID 1 pitfalls.
- Reduce Django Memory Usage per Worker
Lower the memory footprint of Django processes: measure RSS per Gunicorn and Celery worker, trim imports and INSTALLED_APPS, stream large querysets and responses, recycle workers with max-requests, try jemalloc, and size worker counts to fit the server.
Check it
Review lists to run before launch or after a change.
- Gunicorn Production Checklist for Django
A production checklist for running Django on Gunicorn: bind address and socket, worker class and count, timeouts and graceful shutdown, worker recycling, logging, forwarded headers, process supervision, and the proxy in front.
Fix it
Errors and symptoms, each traced to a cause and a fix.
- Fix Gunicorn Socket Permission Denied (Nginx + Django)
Fix Permission denied on a Gunicorn Unix socket: socket ownership and mode, directory traversal, systemd RuntimeDirectory, umask, and SELinux.
- Gunicorn Worker Timeout in Django: Root Causes and Fixes
A Gunicorn worker timeout in Django production usually means a worker process stopped responding before Gunicorn’s timeout limit expired.
- Fix Gunicorn "Failed to find attribute 'application'"
Fix Gunicorn errors that cannot find the Django application object: wrong module or attribute names, shadowed modules, ASGI paths, and wsgi.py mistakes.
- Fix Gunicorn "Address already in use"
Fix Gunicorn Connection in use and Address already in use errors: find the process holding the port or socket, stop duplicate services, and prevent stale sockets.
- Fix Gunicorn Workers Killed by the OOM Killer
Diagnose Gunicorn workers killed for running out of memory: OOM evidence, memory per worker, large querysets, leaks, max-requests, and right-sizing.
- Fix Gunicorn "Worker failed to boot"
Fix Gunicorn HaltServer 'Worker failed to boot' for Django: find the real traceback, reproduce the import with the same environment, and fix settings, imports, and startup-time side effects.
- Fix Gunicorn "Permission denied" Binding to Port 80
Fix Gunicorn Connection in use or Permission denied when binding to port 80 or 443: bind Gunicorn to a high port or Unix socket behind Nginx, or grant CAP_NET_BIND_SERVICE safely instead of running as root.
- Fix uWSGI "no python application found" for Django
Fix uWSGI no python application found, check your startup logs for errors: point module at the right wsgi.py, set chdir and virtualenv, load the Python plugin, and read the import error hidden earlier in the log.
- Fix uWSGI "invalid request block size"
Fix the uWSGI error invalid request block size behind Nginx for Django: use uwsgi_pass instead of proxy_pass for the uwsgi protocol, match socket and http-socket, and raise buffer-size for large cookies and headers.
- Fix Gunicorn "Error Handling Request" and "Ignoring EPIPE" With Django
Understand and fix Gunicorn log lines such as Error handling request, Ignoring EPIPE, and BrokenPipeError with Django: tell client disconnects apart from real errors, align proxy and Gunicorn timeouts, and handle slow uploads and streaming responses.
- Fix "Target WSGI Script Cannot Be Loaded as Python Module" in Apache
Fix the Apache mod_wsgi error Target WSGI script cannot be loaded as Python module for Django: match mod_wsgi to your Python version, set python-home and python-path, fix permissions on the project and virtualenv, and read the real exception below it.
- Django 502 Bad Gateway: Causes and Fixes
A 502 Bad Gateway in a Django deployment usually means your reverse proxy is reachable, but it cannot get a valid response from the upstream app server.
- Fix Nginx Not Connecting to Gunicorn (Connection Refused)
Fix Nginx connect() failed (111: Connection refused) to Gunicorn: service status, bind address mismatches, stale sockets, firewalls, and startup ordering.
- Fix ModuleNotFoundError When Starting Django with Gunicorn
Fix ModuleNotFoundError when Gunicorn starts Django: wrong virtualenv, working directory, project module path, missing packages, and Python version mismatches.
- Fix a Gunicorn systemd Service That Fails to Start
Fix a Gunicorn service for Django that systemd cannot start: status codes 203/EXEC, 200/CHDIR, 217/USER, environment files, socket directories, and restart loops.
- Fix Django Code Changes Not Showing After Deploy
Fix deploys that seem to do nothing: Gunicorn not reloaded, old processes still running, wrong release directory, cached templates, and stale assets.
- Fix a Slow First Request After a Django Deploy
Fix slow first requests after a Django deploy or restart: measure cold versus warm, find heavy imports with -X importtime, precompile bytecode, preload, warm workers, and avoid cold starts.
- Fix Nginx "upstream prematurely closed connection" for Django
Fix the Nginx error upstream prematurely closed connection while reading response header from upstream: find the Gunicorn worker that died or timed out, match timeouts across layers, and fix crashes and memory kills.
- Find and Fix a Django Memory Leak in Production
Find and fix a Django memory leak in production: tell real leaks from normal Python growth, recycle Gunicorn workers, profile with tracemalloc, and fix DEBUG query logging, unbounded caches, and large querysets.
- Fix "ASGI lifespan protocol appears unsupported" Warnings
Understand and silence the Uvicorn message ASGI lifespan protocol appears unsupported when serving Django: why Django does not handle lifespan events, how to turn lifespan off, and where to put startup code instead.
- Fix "No open ports detected" and Port Binding on PaaS Hosts
Fix Django deploys failing on Render, Railway, Fly.io, Cloud Run, and App Runner with no open ports detected, failed to bind to PORT, or application failed to respond: bind Gunicorn to 0.0.0.0 and the platform's PORT variable.
- Fix "You’re Accessing the Development Server Over HTTPS"
Fix the Django runserver error saying you’re accessing the development server over HTTPS but it only supports HTTP: clear cached HSTS, turn off SSL redirects in development, avoid .dev domains, and run local HTTPS properly when you need it.
- Fix cPanel Passenger "Web Application Could Not Be Started" for Django
Fix the Phusion Passenger error page We’re sorry, but something went wrong / Web application could not be started for Django on cPanel: set up passenger_wsgi.py correctly, use the app’s virtualenv, read the stderr log, and fix static files and restarts.
Learning paths through this topic
- Your first production deployment on a VPSFrom a fresh Ubuntu server to a Django site on HTTPS, with the settings and checks that keep it safe.
- Django on KubernetesRun Django on a cluster with config, ingress, probes, jobs, graceful shutdown, and autoscaling, then package it with Helm and GitOps.
- Making Django fastMeasure first, then fix queries, caching, workers, and delivery, and prove it with a load test.