Database connection timeout on PostgreSQL with pgAdmin on macOS 14.4
PostgreSQL connection timeout on macOS 14.4 with pgAdmin 8.x. The fix is disabling IPv6 in the pg_hba.conf or binding to 127.0.0.1.
You're stuck with a timeout when connecting pgAdmin to PostgreSQL on macOS 14.4 Sonoma. It's annoying and kills your flow. Here's the straight fix.
Open Terminal. Edit /usr/local/var/postgresql@15/pg_hba.conf (adjust version number if yours is different). Find this line:
# TYPE DATABASE USER ADDRESS METHOD
# IPv4 local connections:
host all all 127.0.0.1/32 scram-sha-256
# IPv6 local connections:
host all all ::1/128 scram-sha-256
Comment out the IPv6 line by adding # at the start. Or change the address to 127.0.0.1/32 for both. Save the file.
Now edit /usr/local/var/postgresql@15/postgresql.conf. Look for:
#listen_addresses = '*'
Change it to:
listen_addresses = '127.0.0.1'
Restart PostgreSQL:
brew services restart postgresql@15
Now try connecting from pgAdmin again. Should work immediately.
Why this fix works
The timeout happens because pgAdmin, running on macOS 14.4, tries to connect to localhost which resolves to both IPv4 (127.0.0.1) and IPv6 (::1). PostgreSQL by default listens on both, but macOS's new networking stack in Sonoma (since 14.0) has a known quirk: when a client connects via IPv6 to localhost, the initial handshake can hang for up to 30 seconds before falling back to IPv4. This isn't a PostgreSQL bug — it's macOS's mDNSResponder or the kernel's IPv6 stack timing out.
What's actually happening here is that pgAdmin initiates a TCP connection to ::1:5432, PostgreSQL accepts it, but the TLS negotiation (if using SSL) or just the default scram-sha-256 authentication handshake gets stuck because macOS's IPv6 stack processes the SYN/ACK packets with an extra delay. The listen_addresses = '127.0.0.1' forces PostgreSQL to bind only to IPv4, so pgAdmin never even tries IPv6. Same effect if you comment out the IPv6 line in pg_hba.conf — PostgreSQL still listens on IPv6 but refuses connections from ::1, so pgAdmin falls back to IPv4 instantly.
The reason step 3 works is that PostgreSQL reads postgresql.conf first when starting, and binds its sockets to the specified addresses. If you only edit pg_hba.conf, the server still listens on ::1 but rejects the connection with a quicker response, which still triggers a fallback. But binding to 127.0.0.1 entirely avoids the IPv6 path. Both are valid — I prefer the listen_addresses route because it's more explicit.
Less common variations
1. Docker-based PostgreSQL on macOS. If you're running PostgreSQL in a Docker container, the fix is different. The container bridges to your host's network, and macOS's IPv6 issues still bite. Edit your docker-compose.yml or run command to include --net=host or explicitly set listen_addresses = '0.0.0.0' inside the container (not 127.0.0.1). Then connect via your host's IPv4 IP, not localhost. Example:
docker run -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 postgres:15
Still get timeouts? Use --add-host host.docker.internal:host-gateway and connect to host.docker.internal:5432 instead of localhost.
2. SSL certificate mismatch. Some pgAdmin versions (8.0 and newer) enforce stricter SSL checks. If you have a self-signed cert and haven't added it to your keychain, the connection tries, times out, and you see a generic timeout error. Check pgAdmin's connection logs: open ~/.pgadmin/pgadmin4.log. If you see SSL SYSCALL error: EOF detected followed by timeout, that means the SSL handshake failed before the timeout — not a network issue. Solution: either disable SSL in pgAdmin (not recommended) or add your certificate to macOS's keychain via sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /path/to/server.crt.
3. Firewall intervention. On macOS 14.4, the built-in firewall (pfctl) can interfere with loopback connections if you've enabled it explicitly. Check with sudo pfctl -s info. If enabled, add a rule: sudo pfctl -a com.apple/250.SomeService -f /etc/pf.anchors/com.apple/250.SomeService 2>/dev/null || true — this is a deep rabbit hole. Simpler: disable the firewall temporarily to test: sudo pfctl -d. If that fixes it, you know the cause. Re-enable with sudo pfctl -e.
4. Homebrew installation with multiple versions. If you have both PostgreSQL 14 and 15 installed via Homebrew, pgAdmin might be hitting the wrong version's socket. Check which is active: brew services list | grep postgres. Only one should be running. If both are, stop the old one: brew services stop postgresql@14. Then check the port: lsof -i :5432 should show the correct PostgreSQL process.
Prevention
To not hit this again, do three things:
- Bind to 127.0.0.1 by default. Edit postgresql.conf right after installation. It's one line and saves you from this whole class of IPv6-related issues. If you need remote access later, you can expand to specific IPs.
- Set a shorter connection timeout in pgAdmin. In pgAdmin, go to File -> Preferences -> Connections -> Connection timeout. Drop it to 5 seconds. That way a stuck connection fails fast instead of hanging your workflow.
- Use a Unix socket instead of TCP. macOS and PostgreSQL support local sockets natively. In pgAdmin, when adding a server, use
/tmp/.s.PGSQL.5432as the host. This bypasses the network stack entirely — no IPv4 or IPv6 involved. On Homebrew installations the socket is usually at/tmp/.s.PGSQL.5432or/var/run/postgresql/.s.PGSQL.5432. Check withfind /tmp -name '.s.PGSQL.*' 2>/dev/null.
The real fix is understanding the macOS 14.4 IPv6 dance. Once you know it, it's trivial. The key thing: don't let localhost be ambiguous. Force it to IPv4 or skip TCP entirely with a Unix socket. You'll never see that timeout again.
Was this solution helpful?