Cookbook recipe

PgBouncer Auth File Out of Sync

Applies to PostgreSQL 13–17 Last reviewed May 2026 Grounded in source
Estimated investigation4 min

Scenario

Scenario After a password rotation, PgBouncer starts rejecting connections with ERROR: password authentication failed. The DBA updated pg_hba.conf and rotated the PostgreSQL password but forgot to update PgBouncer's userlist.txt (static authentication file). Alternatively, PgBouncer is configured…

Investigation Path

Scenario

After a password rotation, PgBouncer starts rejecting connections with ERROR: password authentication failed. The DBA updated pg_hba.conf and rotated the PostgreSQL password but forgot to update PgBouncer’s userlist.txt (static authentication file). Alternatively, PgBouncer is configured with auth_type = hba but its HBA file doesn’t include the updated credentials path.

How to Identify

Conditions:

  • PgBouncer logs show auth failed even though psql direct connection works
  • userlist.txt (PgBouncer’s auth file) has old MD5 hashes for the user
  • PgBouncer’s auth_file path in pgbouncer.ini doesn’t point to the correct file
  • auth_type = scram-sha-256 in PgBouncer but userlist.txt has MD5 hashes
  • PgBouncer version doesn’t support SCRAM (versions before 1.14)

Analysis Steps

-- On PostgreSQL: verify the password is correct (psql connects successfully)
-- psql -h localhost -U app_user -d mydb -c "SELECT 1;" ← should work

-- On PostgreSQL: check what hash format the password is stored in
SELECT rolname, left(rolpassword, 20) AS hash_prefix
FROM pg_authid
WHERE rolname = 'app_user';
-- 'SCRAM-SHA-256$...' = SCRAM format (PgBouncer 1.14+ required)
-- 'md5...'            = MD5 format (older PgBouncer OK)

-- Check PgBouncer's userlist.txt format (OS-level):
-- cat /etc/pgbouncer/userlist.txt
-- Format: "username" "password_hash_or_plain"
-- Must match PostgreSQL's current password hash format

-- Check PgBouncer config for auth_type:
-- grep auth_type /etc/pgbouncer/pgbouncer.ini
-- auth_type = hba          = PgBouncer uses its own HBA file
-- auth_type = md5          = requires MD5 hashes in userlist.txt
-- auth_type = scram-sha-256 = requires SCRAM hashes (PgBouncer 1.14+)
-- auth_type = plain        = plaintext passwords (insecure)

-- Check PgBouncer version:
-- pgbouncer --version
-- versions < 1.14 do NOT support SCRAM

Pitfalls

  • PgBouncer’s userlist.txt must be manually updated every time a PostgreSQL password changes. This is often forgotten during credential rotations.
  • PgBouncer with auth_type = md5 stores MD5 hashes in userlist.txt. If PostgreSQL is migrated to scram-sha-256, PgBouncer needs upgrade to 1.14+ AND userlist.txt must be updated with SCRAM hashes.
  • PgBouncer’s auth_query feature lets PgBouncer query PostgreSQL for credentials dynamically — this eliminates the userlist.txt sync problem but requires a special lookup function.
  • PgBouncer in transaction pool mode cannot support prepared statements natively — applications using extended query protocol or LISTEN/NOTIFY must use session pool mode.
  • Reloading PgBouncer (pgbouncer -R or kill -HUP) re-reads userlist.txt without dropping existing connections.

Resolution Approach

Update userlist.txt with the new password hash from pg_authid. Reload PgBouncer to apply the change. For long-term, configure auth_query so PgBouncer fetches credentials from PostgreSQL directly — eliminating manual sync.

This is a Pro lesson

Get every Learning Pathway and cookbook recipe — grounded in PostgreSQL source code, with diagnostics, fixes, and prevention for each topic.

Continue this lesson to learn:

  • Mitigation Actions
  • All 36 Learning Pathway lessons
  • 170+ cookbook recipes
  • Source-grounded diagnostics & fixes

Secure checkout Cancel anytime Source-grounded

Career Impact

This scenario builds production judgment and operational confidence under pressure.

Open Career Dashboard →

Keep going

Related & next steps

Was this helpful?

← All cookbook recipes