StackEngine
Initializing Enclave...

Explore More Performance Tools

View All Performance
Performance

PostgreSQL Localhost 5432 Connection Refused

PostgreSQL is not running or not bound to localhost:5432, killing all application database connections instantly.

Performance

PostgreSQL Server Connection Timeout Monitor

PostgreSQL connection timeout errors kill application availability when the server is unreachable, overloaded, or misconfigured — every second of delay compounds into cascading service failure.

Performance

PostgreSQL Client Receive Connection Timeout

PostgreSQL drops the client connection mid-query because the TCP socket stalled past the kernel or load-balancer idle timeout, killing in-flight transactions and causing cascading application failures.

Performance

PostgreSQL Socket Failover Connectivity Auditor

PostgreSQL client throws 'Socket is not connected' post-failover because the connection pool is holding stale TCP sockets that survived the primary switchover without being invalidated.

Performance

PostgreSQL Buffer Space Availability Monitor

PostgreSQL exhausts the OS socket send buffer, dropping client connections with 'no buffer space available' under high-concurrency or misconfigured kernel network stack.

Performance

PostgreSQL Resource Temporarily Unavailable Fix

PostgreSQL drops client connections with 'could not receive data from client: Resource temporarily unavailable' when the OS-level socket read returns EAGAIN under non-blocking I/O, typically caused by exhausted connection slots, misconfigured kernel socket buffers, or a pgBouncer/HAProxy misconfiguration starving the backend.

How to Fix PostgreSQL 'Connection Timed Out' on Port 5432 (Remote Host Debugging Guide)

Threat/Impact Level: HIGH | Exploitability/Downtime Risk: HIGH | Time to Fix: 15–45 mins

TL;DR

  • What broke: TCP packets to db.example.com:5432 are being silently dropped — by a cloud security group, iptables rule, or postgresql.conf binding to 127.0.0.1 only. The client never gets a RST, so it hangs until timeout.
  • How to fix it: Verify listen_addresses in postgresql.conf, open port 5432 in your firewall/security group to the app server's CIDR only, and confirm pg_hba.conf has a matching host record for the remote client IP.
  • Shortcut: Use our Client-Side Sandbox above to auto-refactor your pg_hba.conf and connection string without uploading your credentials anywhere.

The Incident (What does the error mean?)

Raw error output:

psql: error: could not connect to server: Connection timed out
        Is the server running on host 'db.example.com' (203.0.113.45)
        and accepting TCP/IP connections on port 5432?

Immediate consequence: The PostgreSQL client sent a TCP SYN to port 5432. It received nothing — no SYN-ACK, no RST. This is not a refused connection (which would be instant). This is a silent drop, meaning a stateful firewall or security group is eating the packet. Your application thread is now blocking until the OS-level connect timeout fires (default: 20–130 seconds depending on kernel). In a connection-pooled app, this cascades into pool exhaustion within seconds.

Connection refused vs. Connection timed out — know the difference:

Signal Meaning
Connection refused Server is up, port is closed at the OS level (pg_hba or postgres not running)
Connection timed out Firewall/SG is dropping packets. Postgres may be running fine.

The Attack Vector / Blast Radius

A timeout (not a refusal) tells you the network path is the problem. The blast radius depends on your architecture:

1. Cloud Security Group / VPC Firewall (most common cause) If you opened port 5432 to 0.0.0.0/0 as a "temporary" fix and it still times out, your NACLs (Network ACLs) are likely blocking return traffic on ephemeral ports. Conversely, if the SG has no inbound rule for 5432, every connection attempt from every app server silently fails — this is your outage.

2. postgresql.conf bound to localhost only Postgres is running and healthy, but listen_addresses = 'localhost' means it never opens port 5432 on the external interface. From the network's perspective, the port is closed — but depending on your OS/firewall stack, this can manifest as a timeout rather than a refusal.

3. iptables / ufw on the DB host A default-deny iptables policy with no explicit ACCEPT rule for 5432 drops packets before Postgres ever sees them.

Security note: Port 5432 exposed to 0.0.0.0/0 is actively scanned by botnets (Shodan indexes thousands of open PostgreSQL instances). A misconfigured pg_hba.conf with trust auth on a world-accessible port is a full database compromise. Never open 5432 to the internet. Use a bastion, VPN, or VPC peering.


How to Fix It (The Solution)

Step 1 — Isolate the layer

Run this from the application server before touching any config:

# Test raw TCP connectivity (bypasses DNS, tests firewall only)
nc -zv db.example.com 5432

# If nc is unavailable:
timeout 5 bash -c 'cat < /dev/null > /dev/tcp/db.example.com/5432' && echo OPEN || echo BLOCKED

# Trace where packets die:
traceroute -T -p 5432 db.example.com

If nc hangs → firewall/SG layer. Fix Step 2 first. If nc connects but psql still fails → pg_hba.conf or listen_addresses. Jump to Step 3.


Step 2 — Basic Fix: Open the firewall (AWS Security Group example)

# AWS Security Group Inbound Rules (Terraform)
 resource "aws_security_group_rule" "postgres_inbound" {
   type              = "ingress"
   from_port         = 5432
   to_port           = 5432
   protocol          = "tcp"
-  cidr_blocks       = ["0.0.0.0/0"]   # NEVER do this in production
+  cidr_blocks       = ["10.0.1.0/24"] # App server subnet CIDR only
   security_group_id = aws_security_group.db.id
 }
# iptables on the DB host
- # (no rule — default DROP policy)
+ -A INPUT -p tcp -s 10.0.1.0/24 --dport 5432 -m state --state NEW,ESTABLISHED -j ACCEPT
+ -A OUTPUT -p tcp --sport 5432 -m state --state ESTABLISHED -j ACCEPT

Step 3 — Fix `postgresql.conf` (listen address)

# /etc/postgresql/15/main/postgresql.conf
-listen_addresses = 'localhost'
+listen_addresses = '0.0.0.0'   # Or specify the DB server's private IP: '10.0.2.5'

Restart required: systemctl restart postgresql


Step 4 — Fix `pg_hba.conf` (client authentication)

# /etc/postgresql/15/main/pg_hba.conf
 # TYPE  DATABASE  USER       ADDRESS          METHOD
 local   all       all                         peer
 host    all       all        127.0.0.1/32     scram-sha-256
+host    appdb     appuser    10.0.1.0/24      scram-sha-256
-# Missing remote host record = connection refused or timeout depending on OS

Reload (no restart needed for pg_hba): systemctl reload postgresql


Enterprise Best Practice: SSL + restricted user + connection pooling

# pg_hba.conf — enforce SSL for all remote connections
-host    appdb     appuser    10.0.1.0/24      scram-sha-256
+hostssl appdb     appuser    10.0.1.0/24      scram-sha-256
# postgresql.conf
+ssl = on
+ssl_cert_file = '/etc/ssl/certs/server.crt'
+ssl_key_file  = '/etc/ssl/private/server.key'
+ssl_ca_file   = '/etc/ssl/certs/ca.crt'

Never connect as postgres superuser from application code. Create a least-privilege role:

-- Run on the DB server
CREATE ROLE appuser WITH LOGIN PASSWORD 'use-a-vault-secret' CONNECTION LIMIT 50;
GRANT CONNECT ON DATABASE appdb TO appuser;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser;
REVOKE CREATE ON SCHEMA public FROM appuser;

💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure Client-Side WASM utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.


Prevention in CI/CD

1. Checkov — catch open 5432 rules in Terraform before terraform apply:

# .checkov.yml
checks:
  - CKV_AWS_25   # Ensure no security groups allow ingress from 0.0.0.0/0 to port 5432
  - CKV_AWS_382  # Ensure RDS is not publicly accessible
checkov -d ./terraform --check CKV_AWS_25,CKV_AWS_382 --compact

2. OPA/Conftest policy — block world-open DB ports:

# policy/no_public_postgres.rego
package terraform

deny[msg] {
  r := input.resource.aws_security_group_rule[_]
  r.from_port <= 5432
  r.to_port >= 5432
  r.cidr_blocks[_] == "0.0.0.0/0"
  msg := "DENY: PostgreSQL port 5432 must not be open to 0.0.0.0/0"
}

3. GitHub Actions — gate on Checkov scan:

- name: Checkov IaC Scan
  uses: bridgecrewio/checkov-action@master
  with:
    directory: terraform/
    check: CKV_AWS_25,CKV_AWS_382
    soft_fail: false   # Fails the pipeline. Non-negotiable.

4. Connection string validation in app startup:

import psycopg2
from psycopg2 import OperationalError
import sys

try:
    conn = psycopg2.connect(dsn=DATABASE_URL, connect_timeout=5)
except OperationalError as e:
    # Fail fast at startup, not mid-request
    print(f"[FATAL] DB unreachable at startup: {e}", file=sys.stderr)
    sys.exit(1)

5. Monitor for this in production:

  • Alert on pg_stat_activity where wait_event_type = 'Client' and state = 'idle in transaction' exceeding threshold.
  • CloudWatch / Datadog metric: DatabaseConnections spike + CPUUtilization drop = connection timeout storm, not a DB load issue.

Related Diagnostics

"Part of the Performance Utility Matrix."

View all 219 Performance Tools →