ASGI & WebSockets for Django in production
Async Django in production: ASGI servers, Channels, WebSockets, and when async is worth it.
ASGI lets Django hold connections open for WebSockets, server-sent events, and async views. It changes the server, the proxy configuration, and how blocking code behaves.
The guides cover choosing between WSGI and ASGI, deploying Channels with Daphne or Uvicorn, and fixing WebSocket connections that fail or drop.
Set it up
Guides that take this from nothing to running in production.
- 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 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.
- Deploy Django Channels and WebSockets with Daphne
Deploy Django Channels in production with Daphne, a Redis channel layer, systemd, and Nginx WebSocket proxying, while Gunicorn keeps serving regular HTTP traffic.
- 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.
- 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.
- 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.
Run it well
Tuning, reliability, and operations once it works.
- When Async Django Views Pay Off in Production
Decide when async views improve a production Django app: concurrent external API calls, streaming, and long-polling benefit, while ORM-heavy views usually do not. Measure, avoid blocking calls, and run async code under ASGI correctly.
- Scale Django Channels WebSockets Across Servers
Scale Django Channels beyond one process: the Redis channel layer and its capacity settings, running several Daphne or Uvicorn instances behind a load balancer, sticky sessions, connection limits, group fan-out costs, and graceful reconnects during deploys.
Check it
Review lists to run before launch or after a change.
- Django Channels and WebSockets Production Checklist
A production checklist for Django Channels: ASGI server choice, Redis channel layer, WebSocket proxy configuration, authentication and origin checks, consumer performance, scaling, timeouts and heartbeats, deploys, and monitoring.
- Django ASGI Production Checklist
A checklist for running Django under ASGI in production with Uvicorn, Daphne, Granian, or Hypercorn: choose workers, avoid blocking calls in async views, handle sync middleware and the ORM, configure WebSocket proxies and timeouts, lifespan, and graceful shutdown.
Fix it
Errors and symptoms, each traced to a cause and a fix.
- Fix Django WebSocket Connection Failed Behind Nginx
Debug Django Channels WebSocket failures behind Nginx: handshake status codes, Upgrade headers, ASGI routing, origin checks, wss mixed content, and idle timeouts.
- Fix Django SynchronousOnlyOperation in Async Code
Fix Django SynchronousOnlyOperation You cannot call this from an async context: use async ORM methods, sync_to_async for blocking code, avoid lazy relation access in async views and consumers, and never disable the check in production.
- 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 Django WebSockets Disconnecting After 60 Seconds
Fix Django Channels WebSocket connections that drop after about 60 seconds of inactivity: raise Nginx proxy_read_timeout, configure load balancer idle timeouts, and send keepalive pings from the client or server.
- Fix Django Channels WebSocket 403 Forbidden in Production
Fix Django Channels WebSocket connections rejected with 403 or closed with code 1006 in production: configure AllowedHostsOriginValidator and ALLOWED_HOSTS, pass Host and Origin through Nginx, and check authentication middleware and CSRF-like origin rules.
- Fix Django StreamingHttpResponse and SSE Buffered by Nginx
Fix Django StreamingHttpResponse and server-sent events that arrive all at once instead of streaming: disable Nginx proxy buffering with X-Accel-Buffering, avoid GZip middleware on streams, and use async views for long streams.