Pingora’s graceful upgrade mechanism lets you replace a running server binary without interrupting any in-flight HTTP connections. From the client’s perspective the listening socket never closes — there is no window during which a connection attempt would be refused. The mechanism provides two hard guarantees:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/cloudflare/pingora/llms.txt
Use this file to discover all available pages before exploring further.
- No connection refused. Every new connection attempt is handled by either the old server instance or the new one. There is no gap.
- In-flight requests complete. Any request that can finish within the configured grace period is guaranteed not to be terminated mid-flight.
The socket-transfer mechanism relies on Unix domain socket file-descriptor passing and is Linux only. It is not available on macOS or Windows.
Graceful upgrade (SIGQUIT) is distinct from graceful shutdown (SIGTERM). SIGTERM drains the server and exits; SIGQUIT transfers sockets to a new instance first, then drains. Both use the same grace period logic for in-flight requests.
Prerequisites
You need a sharedupgrade_sock path that both the old and new server instances agree on. This path must be set in the configuration file before you start the old server for the first time:
Upgrade Procedure
Add
upgrade_sock to your configuration file. Both the old and new instances must point to the same path. The YAML shown above is the canonical example.Launch the new binary with the
-u / --upgrade flag. Instead of binding to the listening ports immediately, the new instance connects to the upgrade socket and waits for the old instance to hand over the file descriptors:The old instance transfers its listening socket file descriptors to the new instance over the upgrade socket. The new instance immediately begins accepting connections on those sockets. Meanwhile, the old instance stops accepting new connections, waits a short period (to give the new instance time to initialize and start handling traffic), and then enters its graceful shutdown drain — waiting for the grace period before exiting.
Combined Command
For a quick local upgrade (e.g., during development), you can run both steps in sequence. Start the new binary with--upgrade first (it will block waiting on the upgrade socket), then signal the old instance:
What the Client Sees
The listening socket (e.g., TCP port 443) is owned by the operating system, not the process. When the old instance transfers the socket file descriptor to the new instance, the OS-level socket object never closes. Any newconnect() calls from clients are queued in the kernel and served by the new instance as soon as it takes ownership. Clients that were already connected to the old instance continue to be served by it during the drain period.
Old Instance Drain Behavior
After handing off the socket file descriptors, the old instance:- Waits a short fixed period (
CLOSE_TIMEOUT, 5 seconds by default) to give the new process time to initialize and prepare to handle traffic. - Stops accepting any new connections.
- Waits up to the configured grace period (
EXIT_TIMEOUT, 5 minutes by default) for all in-flight requests to finish. - Exits.
