Repository navigation
[Triage] ASGI worker ignores configured keepalive with Django ASGI apps (closes idle connections immediately)
#3655
josema-xyz
started this conversation in
Issue Triage
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Type
Bug Report
Description
The native
asgiworker does not honor the configuredkeepalivewhen serving a Django ASGI application: it closes idle keep-alive connections immediately after the response, with noConnection: closeheader.The same worker, same version, same config keeps connections alive for the full
keepaliveduration when serving a bare ASGI app. Only swapping the app for Django'sget_asgi_application()(no database, no middleware) triggers the early close. The control socket confirms the value is loaded (keepalive: 30), so it is read but not applied for these connections.Behind a load balancer that pools and reuses upstream connections (e.g. an AWS ALB with a 60s+ idle timeout), the balancer reuses a socket the worker has already closed and returns 502s that never reach the application. Running the same Django app under the uvicorn worker (which honors its own keep-alive timeout) makes it go away.
Steps to Reproduce (for bugs)
Minimal, no DB and no middleware.
keepalive = 30, one worker.app_bare.pyapp_django.pytest.py(sends one request, then times how long the idle connection stays open)Steps:
gunicorn -c config.py app_bare:app, thenpython test.py-> connection held ~30s (correct).gunicorn -c config.py app_django:app, thenpython test.py-> connection closed at ~0.00s (bug).app_djangounderworker_class = "uvicorn_worker.UvicornWorker"withtimeout_keep_alive = 30-> held ~30s (works).Configuration
Logs / Error Output
Gunicorn Version
gunicorn (version 26.0.0)
Python Version
Python 3.12.12
Worker Class
asgi (beta)
Operating System
macOS 15, also on Docker with Debian bookworm (python:3.12-slim)
Additional Context
Behavior matrix (idle connection held vs configured
keepalive = 30):asgiworkerasgiworker is fine, so this looks specific to the interaction between Django'sASGIHandlerand the native worker's keep-alive handling.Connection: closeheader is sent, so a fronting load balancer keeps the connection pooled and reuses a closed socket -> ELB 502s with no target log entry.uvicorn-worker) withtimeout_keep_aliveset; keep-alive then behaves as configured.Checklist
All reactions