gss_accept_delegation is a boolean, it defaults to off, and its context is sighup. It controls whether your PostgreSQL server will accept Kerberos credentials that a client hands it, and the reason it defaults to off is that accepting them means the server can then turn around and act as that user against other systems. This is one of those parameters where the default is the secure choice and turning it on is a deliberate decision to take on risk in exchange for a capability. So the useful thing this post can do is explain the capability, the risk, and how to tell whether you actually want the trade.
What delegation is
Start with ordinary Kerberos, because the delegation case is a specific extension of it.
Under GSSAPI with Kerberos, a client proves its identity to the PostgreSQL server without sending a password. The client already holds a ticket-granting ticket from the KDC, obtained when they ran kinit or logged into their workstation, and the authentication exchange proves possession of it. The server learns who you are. That is where it normally stops: the server knows your identity, but it cannot use it. It has no way to go act as you anywhere else.
Credential delegation changes that. When a client delegates, it forwards its actual Kerberos credentials to the server, not just a proof of identity but a usable ticket-granting ticket. The server now holds credentials it can present to a third service as you. Delegation is what makes the server able to be the client downstream, rather than merely knowing who the client is.
This is a capability that exists in Kerberos generally. PuTTY, OpenSSH, and Windows all have their own switches for it, and the concept is the same everywhere: the intermediate machine gets to reuse your identity onward.
Why PostgreSQL wants it
The feature landed in PostgreSQL 16, contributed by Stephen Frost, and the motivating case is the foreign data wrapper.
Consider postgres_fdw connecting your database to a second PostgreSQL server. Without delegation, that second server has to be told how to authenticate the connection coming from the first, and the usual answers are unattractive: a password stored in the user mapping, or a service account that every user’s queries run as, which collapses everyone’s access into one identity and destroys your audit trail on the remote side.
With delegation, none of that is needed. A user authenticates to the first server with their own Kerberos credentials and delegates them. The first server uses those delegated credentials to authenticate to the second server as that same user. The remote server sees the real end user, applies that user’s permissions, and logs that user’s activity. The identity is carried all the way through the chain instead of being replaced at the boundary. dblink gets the same benefit.
That is a genuinely good property. Single sign-on that survives a hop, with per-user authorization on the far side, is exactly what you want in a Kerberos shop, and it is worth building toward when it fits.
Why it is off, and what turning it on costs
Now the other side, because the cost is real and specific.
A server that accepts delegated credentials is holding live, usable credentials for every user who connects and delegates. Those are not proofs of identity; they are the keys themselves, sitting in the memory of the database process for the life of the backend. Anyone who can compromise the database server, or read the memory of its processes, or otherwise get inside it, can use those credentials to act as your users against every service those credentials reach, not just the database. The blast radius of a server compromise stops being “the data in this database” and becomes “everything these users can authenticate to.”
This is why the community argued carefully about defaults during development. The design question that got the most scrutiny was whether accepting delegation could be safely turned on by default, and the answer was no, precisely because turning it on changes what a compromise of the server means. Off by default is the correct posture: a server does not take custody of its users’ credentials unless an administrator has decided, explicitly, that the trade is worth it.
To store those credentials the backend needs a Kerberos credential cache, and by default PostgreSQL keeps it in memory rather than on disk, via the MEMORY: cache type, so the delegated credentials do not get written to the filesystem. That is a deliberate hardening of an already sensitive feature, not a reason to relax about it.
It takes four things to line up
The single GUC is necessary but nowhere near sufficient, and this is the part worth internalizing, because it means you do not enable delegation by accident.
Turning on gss_accept_delegation requires, all together: the server GUC set to on; the client choosing to delegate, via libpq’s gssdelegation=1 connection option or the PGGSSDELEGATION environment variable, which itself defaults to 0; the relevant pg_hba.conf line permitting it, since the gss authentication method carries its own per-line control over whether delegated credentials are accepted; and the Kerberos tickets themselves being forwardable, which is a KDC and client configuration matter. Miss any one and no credential is delegated.
That layering is a feature. Delegation is powerful enough that the design does not let a single misconfiguration switch it on. Both ends of the connection, the host-based authentication rules, and the ticket policy all have to agree.
Knowing whether it happened
Because delegation is invisible in the usual sense, nothing about a query announces that the credentials behind it were delegated, PostgreSQL gives you a place to look. The pg_stat_gssapi view has a credentials_delegated column, so you can see per connection whether GSSAPI was used, whether the connection was GSS-encrypted, and whether credentials were in fact delegated on it. If you run this feature, that view is how you confirm it is behaving as intended, and how you would notice delegation happening on connections where you did not expect it.
What to do
For almost everyone, nothing: leave gss_accept_delegation at off. If you are not running Kerberos, or you have no cross-server flow like postgres_fdw or dblink that would benefit from carrying identity across a hop, there is no reason to enable it and a clear reason not to, which is that you would be signing your server up to hold credentials it has no use for.
If you are running Kerberos and you do have that cross-server flow, delegation is a legitimately good design and often the right one, but treat enabling it as the security decision it is. Understand that the delegating server becomes a high-value target because it holds usable credentials, and secure it accordingly: restrict who can reach it, keep the credential cache in memory, and require GSS encryption on the onward connection so the delegated credentials are not exposed in transit. Turn it on deliberately, for a specific flow, with the four preconditions understood, and watch pg_stat_gssapi to confirm it is doing what you meant and nothing more.
The default is off because the safe choice and the do-nothing choice happen, for once, to be the same choice. Change it only when you can say precisely what you are getting and what you are now responsible for protecting.