When you add proxying and the binary protocol to the mix, those hours can multiply fast. Database roles in Postgres are powerful, but their design assumes direct connections. The moment a binary protocol proxy sits between your application and your database, you have to think differently about authentication, authorization, and role switching.
Postgres supports two types of roles: login roles and group roles. Login roles can connect to the database. Group roles collect permissions and can be granted to other roles. The binary protocol sends role information during the startup message. When a proxy is in place, this handshake can be intercepted, altered, or mapped to entirely different upstream roles. This makes understanding the mapping behavior crucial.
A proxy using the Postgres binary protocol can preserve the startup packet and credentials exactly or map them to a fixed role in the backend. If it preserves everything, role-based access works as usual—but latency and security overhead need to be considered. If mapping occurs, you must design your role structure to fit the proxy's capabilities. Without care, you can lose the ability to dynamically switch roles mid-session using SET ROLE, which some applications rely on for privilege minimization.
Another wrinkle appears with connection pooling. Poolers that work at the binary protocol level often reuse backend connections across different clients. That means roles must either be reset before reuse or configured for “role safety” so lingering privileges from prior sessions are impossible. The safest poolers force a DISCARD ALL or equivalent cleanup before resuming work.