Add read-only disconnect_requested GUC for graceful client disconnect

Started by Jelte Fennema-Nio2 months ago1 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253051
psql -h localhost -U postgres

Built from patchset v1 (message #1), September 21, 2026 at 12:08 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253051_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253051_1 && git checkout t253051_1

Patchset v1 (message #1) is on t253051_1

Jump to latest
#1Jelte Fennema-Nio
postgres@jeltef.nl

This is a redesign of the previous GoAway proposal[4]/messages/by-id/DDPQ1RV5FE9U.I2WW34NGRD8Z@jeltef.nl but this time
*without making any protocol changes*:

This commit introduces a new read-only disconnect_requested GUC (similar
to in_hot_standby) that the server can turn on to politely request the
client to disconnect/reconnect when convenient. Because the GUC is
flagged GUC_REPORT, its new value is reported to the client in a
ParameterStatus message whenever it changes. This request is advisory
only: the connection remains fully functional and clients may continue
executing queries and starting new transactions. "When convenient" is
obviously not very well defined, but the primary targets are clients
that maintain a connection pool. Such clients should
disconnect/reconnect a connection in the pool when there's no user of
that connection. This is similar to how such clients often currently
remove a connection from the pool after the connection hits a maximum
lifetime of e.g. 1 hour[1]https://www.pgbouncer.org/config.html#server_lifetime[2]https://github.com/brettwooldridge/HikariCP (see maxLifetime setting). Since psql does not have such a
connection pool all it does is tell the user when the GUC changes, so
that the user might choose a "convenient" time themselves.

The GUC defaults to "off" and is set to "on" by the server in two
situations:
1. Using a new pg_request_disconnect_backend(pid) function the GUC can be
set to "on" for a specific backend using a procsignal.
2. During "smart" shutdown the GUC is set to "on" for all backends.

The pg_request_disconnect_backend() function is effectively a graceful
counterpart to pg_terminate_backend(). This function can be useful to
trigger a graceful reconnect of a specific backend. This can for
instance be used if the backend is using a lot of memory, and an
operator wants the client to reconnect to clear its catalog caches
but without causing any queries to fail.

The "smart" shutdown mode (aka sending SIGTERM to postmaster) is in
practice usually the *least smart* shutdown mode that a user can use. A
single client can indefinitely keep the server from actually shutting
down, while any new connection attempts will be greeted with a FATAL
error. That's not the behavior you want for your primary in production.
The only usage for smart shutdown that currently makes sense is for a
graceful shutdown or switchover of a read replica. Setting
disconnect_requested to "on" during smart shutdown allows for
cooperating clients to disconnect earlier and thus for the
shutdown/switchover to complete quicker.

It can now even make sense to use "smart" shutdown for a primary too, as
long as it's done in combination with "fast" shutdown: If you first
trigger a "smart" shutdown and then trigger a "fast" shutdown after
5 seconds, then all the cooperating clients will have disconnected
gracefully before the fast shutdown would have killed them
mid-transaction. Gracefully recovering from a shutdown mid-transaction
is often non-trivial for an application. Clients might be receiving errors
for later reconnection attempts, but those are often much easier to
handle gracefully (a simple retry is all that's needed).

Finally, this new setting is also intended to be advertised by other
servers implementing the Postgres protocol. For instance proxies like
PgBouncer can send a ParameterStatus message that sets
disconnect_requested to "on" when they want their clients to disconnect
so they can do a rolling restart or switchover without any downtime.
Specifically PgBouncer would be sending this when an operator shuts it
down using SHUTDOWN WAIT_FOR_CLIENTS[3]https://www.pgbouncer.org/usage.html#shutdown.

Two notes of suboptimal behavior:
1. Proxies using this to report their own shutdown will cause the value
of the ParameterStatus to be different than the value that
"SHOW disconnect_requested" reports, unless they also intercept those
queries.
2. Right now the ParameterStatus is only sent at completion of a query,
not while a connection is idle. It'd be better if a connection pool
could check the current state of idle connections too, before handing
them off again. I'll address this in a follow-up commit once it's
agreed on that the general approach is sensible.

[1]: https://www.pgbouncer.org/config.html#server_lifetime
[2]: https://github.com/brettwooldridge/HikariCP (see maxLifetime setting)
[3]: https://www.pgbouncer.org/usage.html#shutdown
[4]: /messages/by-id/DDPQ1RV5FE9U.I2WW34NGRD8Z@jeltef.nl

Attachments:

t253051_1
v1-0001-Add-read-only-disconnect_requested-GUC-for-gracef.patchtext/x-patch; charset=utf-8; name=v1-0001-Add-read-only-disconnect_requested-GUC-for-gracef.patchDownload+432-13