[go: up one dir, main page]

Skip to content

Changelog - 2026

25.1.0 - 2026-02-13

New Features

  • Control Interface (gunicornc): Add interactive control interface for managing running Gunicorn instances, similar to birdc for BIRD routing daemon (PR #3505)
  • Unix socket-based communication with JSON protocol
  • Interactive mode with readline support and command history
  • Commands: show all/workers/dirty/config/stats/listeners
  • Worker management: worker add/remove/kill, dirty add/remove
  • Server control: reload, reopen, shutdown
  • New settings: --control-socket, --control-socket-mode, --no-control-socket
  • New CLI tool: gunicornc for connecting to control socket
  • See Control Interface Guide for details

  • Dirty Stash: Add global shared state between workers via dirty.stash (PR #3503)

  • In-memory key-value store accessible by all workers
  • Supports get, set, delete, clear, keys, and has operations
  • Useful for sharing state like feature flags, rate limits, or cached data

  • Dirty Binary Protocol: Implement efficient binary protocol for dirty arbiter IPC using TLV (Type-Length-Value) encoding (PR #3500)

  • More efficient than JSON for binary data
  • Supports all Python types: str, bytes, int, float, bool, None, list, dict
  • Better performance for large payloads

  • Dirty TTIN/TTOU Signals: Add dynamic worker scaling for dirty arbiters (PR #3504)

  • Send SIGTTIN to increase dirty workers
  • Send SIGTTOU to decrease dirty workers
  • Respects minimum worker constraints from app configurations

Changes

  • ASGI Worker: Promoted from beta to stable
  • Dirty Arbiters: Now marked as beta feature

Documentation

  • Fix Markdown formatting in /configure documentation

25.0.3 - 2026-02-07

Bug Fixes

  • Fix RuntimeError when StopIteration is raised inside ASGI response body coroutine (PEP 479 compliance)

  • Fix deprecation warning for passing maxsplit as positional argument in re.split() (Python 3.13+)


25.0.2 - 2026-02-06

Bug Fixes

  • Fix ASGI concurrent request failures through nginx proxy by normalizing sockaddr tuples to handle both 2-tuple (IPv4) and 4-tuple (IPv6) formats (PR #3485)

  • Fix graceful disconnect handling for ASGI worker to properly handle client disconnects without raising exceptions (PR #3485)

  • Fix lazy import of dirty module for gevent compatibility - prevents import errors when concurrent.futures is imported before gevent monkey-patching (PR #3483)

Changes

  • Refactor: Extract _normalize_sockaddr utility function for consistent socket address handling across workers

  • Add license headers to all Python source files

  • Update copyright year to 2026 in LICENSE and NOTICE files


25.0.1 - 2026-02-02

Bug Fixes

  • Fix ASGI streaming responses (SSE) hanging: add chunked transfer encoding for HTTP/1.1 responses without Content-Length header. Without chunked encoding, clients wait for connection close to determine end-of-response.

Changes

  • Update celery_alternative example to use FastAPI with native ASGI worker and uvloop for async task execution

Testing

  • Add ASGI compliance test suite with Docker-based integration tests covering HTTP, WebSocket, streaming, lifespan, framework integration (Starlette, FastAPI), HTTP/2, and concurrency scenarios

25.0.0 - 2026-02-01

New Features

  • Dirty Arbiters: Separate process pool for executing long-running, blocking operations (AI model loading, heavy computation) without blocking HTTP workers (PR #3460)
  • Inspired by Erlang's dirty schedulers
  • Asyncio-based with Unix socket IPC
  • Stateful workers that persist loaded resources
  • New settings: --dirty-app, --dirty-workers, --dirty-timeout, --dirty-threads, --dirty-graceful-timeout
  • Lifecycle hooks: on_dirty_starting, dirty_post_fork, dirty_worker_init, dirty_worker_exit

  • Per-App Worker Allocation for Dirty Arbiters: Control how many dirty workers load each app for memory optimization with heavy models (PR #3473)

  • Set workers class attribute on DirtyApp (e.g., workers = 2)
  • Or use config format module:class:N (e.g., myapp:HeavyModel:2)
  • Requests automatically routed to workers with the target app
  • New exception DirtyNoWorkersAvailableError for graceful error handling
  • Example: 8 workers × 10GB model = 80GB → with workers=2: 20GB (75% savings)

  • HTTP/2 Support (Beta): Native HTTP/2 (RFC 7540) support for improved performance with modern clients (PR #3468)

  • Multiplexed streams over a single connection
  • Header compression (HPACK)
  • Flow control and stream prioritization
  • Works with gthread, gevent, and ASGI workers
  • New settings: --http-protocols, --http2-max-concurrent-streams, --http2-initial-window-size, --http2-max-frame-size, --http2-max-header-list-size
  • Requires SSL/TLS and h2 library: pip install gunicorn[http2]
  • See HTTP/2 Guide for details
  • New example: examples/http2_gevent/ with Docker and tests

  • HTTP 103 Early Hints: Support for RFC 8297 Early Hints to enable browsers to preload resources before the final response (PR #3468)

  • WSGI: environ['wsgi.early_hints'](headers) callback
  • ASGI: http.response.informational message type
  • Works with both HTTP/1.1 and HTTP/2

  • uWSGI Protocol for ASGI Worker: The ASGI worker now supports receiving requests via the uWSGI binary protocol from nginx (PR #3467)

Bug Fixes

  • Fix HTTP/2 ALPN negotiation for gevent and eventlet workers when do_handshake_on_connect is False (the default). The TLS handshake is now explicitly performed before checking selected_alpn_protocol().

  • Fix setproctitle initialization with systemd socket activation (#3465)

  • Fix Expect: 100-continue handling: ignore the header for HTTP/1.0 requests since 100-continue is only valid for HTTP/1.1+ (PR #3463)

  • Fix missing _expected_100_continue attribute in UWSGIRequest

  • Disable setproctitle on macOS to prevent segfaults during process title updates

  • Publish full exception traceback when the application fails to load (#3462)

Deprecations

  • Eventlet Worker: The eventlet worker is deprecated and will be removed in Gunicorn 26.0. Eventlet itself is no longer actively maintained. Please migrate to gevent, gthread, or another supported worker type.

Changes

  • Remove obsolete Makefile targets (PR #3471)

24.1.1 - 2026-01-24

Bug Fixes

  • Fix forwarded_allow_ips and proxy_allow_ips to remain as strings for backward compatibility with external tools like uvicorn. Network validation now uses strict mode to detect invalid CIDR notation (e.g., 192.168.1.1/24 where host bits are set) (#3458, PR #3459)

24.1.0 - 2026-01-23

New Features

  • Official Docker Image: Gunicorn now publishes official Docker images to GitHub Container Registry at ghcr.io/benoitc/gunicorn
  • Based on Python 3.12 slim image
  • Uses recommended worker formula (2 × CPU + 1)
  • Configurable via environment variables

  • PROXY Protocol v2 Support: Extended PROXY protocol implementation to support the binary v2 format in addition to the existing text-based v1 format (PR #3451)

  • New --proxy-protocol modes: off, v1, v2, auto
  • auto mode (default when enabled) detects v1 or v2 automatically
  • v2 binary format is more efficient and supports additional metadata
  • Works with HAProxy, AWS NLB/ALB, and other PROXY protocol v2 sources

  • CIDR Network Support: --forwarded-allow-ips and --proxy-allow-from now accept CIDR notation (e.g., 192.168.0.0/16) for specifying trusted networks (PR #3449)

  • Socket Backlog Metric: New gunicorn.socket.backlog gauge metric reports the current socket backlog size on Linux systems (PR #3450)

  • InotifyReloader Enhancement: The inotify-based reloader now watches newly imported modules, not just those loaded at startup (PR #3447)

Bug Fixes

  • Fix signal handling regression where SIGCLD alias caused "Unhandled signal: cld" errors on Linux when workers fail during boot (#3453)

  • Fix socket blocking mode on keepalive connections preventing SSL handshake failures with async workers (PR #3452)

  • Use smaller buffer size in finish_body() for faster timeout detection on slow or abandoned connections (PR #3453)

  • Handle SSLWantReadError in finish_body() to prevent worker hangs during SSL renegotiation (PR #3448)

  • Log SIGTERM as info level instead of warning to reduce noise in orchestrated environments (PR #3446)

  • Print exception details to stderr when worker fails to boot (PR #3443)

  • Fix unreader.unread() to prepend data to buffer instead of appending (PR #3442)

  • Prevent RecursionError when pickling Config objects (PR #3441)

  • Use proper exception chaining with raise from in glogging.py (PR #3440)


24.0.0 - 2026-01-23

New Features

  • ASGI Worker (Beta): Native asyncio-based ASGI support for running async Python frameworks like FastAPI, Starlette, and Quart without external dependencies (PR #3444)
  • HTTP/1.1 with keepalive connections
  • WebSocket support
  • Lifespan protocol for startup/shutdown hooks
  • Optional uvloop for improved performance
  • New settings: --asgi-loop, --asgi-lifespan, --root-path

  • uWSGI Binary Protocol: Support for receiving requests from nginx via uwsgi_pass directive, enabling efficient binary protocol communication (PR #3444)

  • New settings: --protocol uwsgi, --uwsgi-allow-from

  • Documentation Migration: Migrated documentation from Sphinx to MkDocs with Material theme for improved navigation and mobile experience (PR #3426)

Security

  • eventlet: Require eventlet >= 0.40.3 to address CVE-2021-21419 (websocket memory exhaustion) and CVE-2025-58068 (HTTP request smuggling) (PR #3445)

  • gevent: Require gevent >= 24.10.1 to address CVE-2023-41419 (HTTP request smuggling) and CVE-2024-3219 (socket.socketpair vulnerability) (PR #3445)

  • tornado: Require tornado >= 6.5.0 to address CVE-2025-47287 (HTTP request smuggling) and other security fixes (PR #3445)

Changes

  • Documentation now hosted at https://gunicorn.org
  • Updated license configuration to PEP 639 format for uv compatibility

ASGI Worker Beta

The ASGI worker is a beta feature. While tested, the API and behavior may change in future releases. Please report any issues on GitHub.