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.

Problem statement

Hypercorn is an ASGI server (it also serves WSGI apps) that supports HTTP/1.1, HTTP/2, WebSockets, and HTTP/3, with asyncio or Trio. Django teams consider it when they want HTTP/2 directly from the app server, Trio support, or an alternative to Uvicorn for async views and Channels. Running it in production needs the same care as any app server: the right worker model, binding behind a reverse proxy, process supervision, and graceful shutdown.

Django with HypercornNginxTLS, static filesHypercornASGI workersDjango ASGI appasync and sync viewssystemdsupervises workersHypercorn runs the ASGI app; Nginx still handles TLS, static files, and buffering.
  1. pip install hypercorn and serve the ASGI app: hypercorn config.asgi:application --bind unix:/run/hypercorn/app.sock --workers 3.
  2. Use the default asyncio worker class (or uvloop for speed); use trio only if your code uses Trio.
  3. Put Nginx in front for TLS, static files, and buffering; proxy to the socket.
  4. Configure with a TOML file for repeatability (--config hypercorn.toml).
  5. Run under systemd with Restart=on-failure and a stop timeout above graceful_timeout.
  6. Serve WSGI instead with config.wsgi:application if you have no async code.

Step-by-step solution

1. Install and test

pip install "hypercorn[uvloop]"
hypercorn config.asgi:application --bind 127.0.0.1:8000

Your config/asgi.py is the standard get_asgi_application() (or a Channels ProtocolTypeRouter). Sync views work under ASGI; Django runs them in a thread pool.

2. Configure with TOML

# /srv/app/hypercorn.toml
bind = ["unix:/run/hypercorn/app.sock"]
workers = 3
worker_class = "uvloop"
keep_alive_timeout = 75
graceful_timeout = 30
accesslog = "-"
errorlog = "-"
umask = 0o007

workers are separate processes; each runs an event loop. Start with roughly the number of CPU cores and adjust based on memory and load. Each worker handles many concurrent connections, so async views and WebSockets scale within a worker.

choosing an app serverHypercornUvicornGunicornProtocolsASGI and WSGIASGIWSGI (ASGI via workers)HTTP/2 and HTTP/3✓yes (H3 optional)HTTP/1.1 onlyHTTP/1.1 onlyEvent loopsasyncio, uvloop, trioasyncio, uvloopn/a for syncTypical useasync, HTTP/2, Trioasync Django, Channelsclassic sync DjangoBehind Nginx, HTTP/2 to clients comes from Nginx anywaydjango-deployment.com
Pick Hypercorn for its protocol or Trio support, not for raw speed.

3. Supervise with systemd

# /etc/systemd/system/hypercorn.service
[Unit]
Description=Django via Hypercorn
After=network.target

[Service]
User=deploy
Group=www-data
WorkingDirectory=/srv/app
EnvironmentFile=/etc/myapp/env
RuntimeDirectory=hypercorn
ExecStart=/srv/app/.venv/bin/hypercorn --config /srv/app/hypercorn.toml config.asgi:application
Restart=on-failure
TimeoutStopSec=40
KillSignal=SIGTERM

[Install]
WantedBy=multi-user.target

TimeoutStopSec above graceful_timeout lets in-flight requests finish during restarts.

4. Put Nginx in front

upstream hypercorn { server unix:/run/hypercorn/app.sock; }

server {
    listen 443 ssl;
    http2 on;
    server_name example.com;
    location /static/ { alias /srv/app/staticfiles/; }
    location / {
        proxy_pass http://hypercorn;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

Nginx provides HTTP/2 to browsers and speaks HTTP/1.1 to Hypercorn, which is the usual and simplest setup. Hypercorn's own HTTP/2 and HTTP/3 support matters when it faces clients directly, which is uncommon in production.

5. Settings for the proxy

SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
ALLOWED_HOSTS = ["example.com"]

Hypercorn can also apply forwarded headers itself; with Nginx overwriting them, Django's setting is enough.

Hypercorn in productionConfig in hypercorn.tomlworkers, bind, timeoutsUnix socket behind NginxTLS and static at the proxysystemd with graceful stopTimeoutStopSec > graceful_timeoutWebSocket headers forwardedUpgrade and ConnectionAsync code avoids blocking callsuse async ORM or sync_to_asyncThe checklist matches Uvicorn because the deployment model is the samedjango-deployment.com
Blocking calls in async views stall every connection on that worker.

Verification check: systemctl status hypercorn is active, curl -I https://example.com returns 200 over HTTP/2 from Nginx, and a WebSocket test (if you use Channels) connects through the proxy. Restart the service during a slow request and confirm it completes.

Explanation

Hypercorn implements the ASGI specification with protocol handling based on the h11, h2, and optional aioquic libraries, and supports both asyncio and Trio event loops. For Django, it plays the same role as Uvicorn: it turns network traffic into ASGI events and passes them to Django's ASGI handler. Performance is broadly similar for typical Django workloads, which are dominated by database and Python time rather than protocol parsing, so the choice usually comes down to features such as HTTP/2 and Trio.

Edge cases / notes

  • Lifespan. Django does not implement ASGI lifespan events; Hypercorn handles this quietly, but log noise can occur on some versions.
  • Static files through Hypercorn work with WhiteNoise but are better served by Nginx.
  • WSGI apps run in a thread pool inside Hypercorn; Gunicorn is more battle-tested for pure WSGI.
  • Max requests. Hypercorn has max_requests with jitter to recycle workers, useful for memory growth.

Next steps

FAQ

Is Hypercorn production-ready for Django?

Yes. It is a mature ASGI server; run it behind Nginx with systemd like any app server.

Hypercorn or Uvicorn for Django?

Uvicorn is more common. Choose Hypercorn for built-in HTTP/2 and HTTP/3 or Trio support.

Can Hypercorn serve WSGI Django?

Yes, by pointing it at config.wsgi:application. Gunicorn remains the more common WSGI choice.

Do I still need Nginx with Hypercorn?

Yes, for TLS, static files, buffering, and protection from slow clients.

Keep going