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 Remote Server Connection Timeout

PostgreSQL remote connection times out because a firewall, security group, or misconfigured pg_hba.conf is silently dropping TCP packets on port 5432 before the handshake completes.

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 Network Partition Broken Pipe Fix

A network partition between client and PostgreSQL server tears down the TCP connection mid-transfer, producing a Broken pipe error that silently drops in-flight transactions and stalls connection pools.

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 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 'could not connect to server: timeout expired' — Root Cause Diagnosis & Production Fix

Threat/Impact Level: HIGH | Downtime Risk: HIGH | Time to Fix: 5–30 mins depending on root cause

TL;DR

  • What broke: PostgreSQL client cannot establish a TCP connection to the server — the socket handshake never completes before the timeout threshold is hit.
  • How to fix it: Isolate the failure layer in order: network/firewall → listen_addresses binding → pg_hba.conf rules → connection pool saturation → server-side max_connections.
  • Fast path: Use our Client-Side Sandbox above to auto-refactor this — paste your postgresql.conf, connection string, or pg_hba.conf and get a corrected config without sending secrets to a third-party server.

The Incident (What Does This Error Mean?)

Raw error output from psql or your application driver:

psql: error: could not connect to server: Connection timed out
        Is the server running on host "db.internal.prod" (10.0.4.22) and accepting
        TCP/IP connections on port 5432?

Or from a Node.js / Python app:

Error: connect ETIMEDOUT 10.0.4.22:5432
OperationalError: could not connect to server: timeout expired

Immediate consequence: The TCP SYN packet sent to port 5432 received no SYN-ACK. The connection was not actively refused (that would be ECONNREFUSED) — it was silently dropped. This means the packet is being eaten by a firewall, a security group, a misconfigured network ACL, or the PostgreSQL process is not listening on the expected interface. Your application's connection pool is now blocking all threads waiting for a socket that will never open, cascading into full application hang within seconds.


The Attack Vector / Blast Radius

This error is not just an ops nuisance — it has a direct blast radius on production availability:

1. Connection Pool Thread Starvation Every application thread (Tomcat, Gunicorn, Node worker) that calls getConnection() blocks until connect_timeout expires. With a default timeout of 30s and a pool size of 20, you have 600 seconds of aggregate blocking capacity being consumed simultaneously. The app goes unresponsive to all users, not just database-dependent routes.

2. Retry Storm Amplification Poorly configured retry logic (no exponential backoff, no circuit breaker) causes the application to hammer the unreachable endpoint. If the timeout is a transient network partition and the server recovers, it is immediately overwhelmed by the accumulated retry queue — turning a 30-second blip into a 5-minute outage.

3. Silent Data Corruption Risk Applications that do not properly handle ETIMEDOUT on in-flight write transactions may assume success. Depending on ORM configuration (autoCommit, transaction isolation), this can result in partial writes or duplicate-key violations when the connection is retried.

4. Security Misconfiguration Exposure If listen_addresses = '*' was set to "fix" a connection issue without tightening pg_hba.conf, the PostgreSQL port is now bound to all interfaces including public-facing ones. A timeout error "fixed" by opening the firewall broadly is a critical security regression — the database becomes directly internet-scannable.


How to Fix It (The Solution)

Step 1: Confirm the TCP layer first

Before touching any config, confirm whether the port is reachable at all:

# From the application server:
nc -zv 10.0.4.22 5432
traceroute 10.0.4.22

# Check if PostgreSQL is actually listening:
sudo ss -tlnp | grep 5432
# or
sudo netstat -tlnp | grep postgres

If nc times out → the problem is network/firewall, not PostgreSQL config. Check security groups, NACLs, or iptables rules first.

If ss shows PostgreSQL is NOT listening on 0.0.0.0:5432 or your target IP → the problem is listen_addresses.


Basic Fix — `listen_addresses` and `pg_hba.conf`

The most common root cause on a freshly deployed server: PostgreSQL defaults to listening only on localhost.

# /etc/postgresql/15/main/postgresql.conf

- listen_addresses = 'localhost'
+ listen_addresses = '10.0.4.22'   # Bind to the private interface only, NOT '*'
# /etc/postgresql/15/main/pg_hba.conf
# Add an explicit rule for your application subnet

- # No entry for 10.0.5.0/24 (app server subnet)
+ host    myappdb    appuser    10.0.5.0/24    scram-sha-256

After editing:

sudo systemctl reload postgresql
# Reload is sufficient for pg_hba.conf changes.
# postgresql.conf listen_addresses change requires full restart:
sudo systemctl restart postgresql

Enterprise Best Practice — Layered Defense with Connection Pooling and Timeout Tuning

Never expose PostgreSQL directly to application servers in production. Use PgBouncer as a connection proxy and enforce strict timeout budgets at every layer.

# /etc/postgresql/15/main/postgresql.conf

- listen_addresses = '*'
- max_connections = 500
+ listen_addresses = '127.0.0.1'   # PgBouncer runs on the same host or private VLAN
+ max_connections = 100             # PgBouncer manages the pool; DB sees far fewer connections

# Add explicit timeout guards:
- #tcp_keepalives_idle = 0
- #tcp_keepalives_interval = 0
- #tcp_keepalives_count = 0
+ tcp_keepalives_idle = 60
+ tcp_keepalives_interval = 10
+ tcp_keepalives_count = 6
+ statement_timeout = '30s'
+ idle_in_transaction_session_timeout = '60s'
# /etc/pgbouncer/pgbouncer.ini

- listen_addr = *
- auth_type = trust
+ listen_addr = 10.0.4.22          # Private interface only
+ auth_type = scram-sha-256
+ pool_mode = transaction           # Transaction pooling for stateless apps
+ max_client_conn = 1000
+ default_pool_size = 25
+ server_connect_timeout = 10       # Fail fast to PgBouncer; don't let clients block
+ server_idle_timeout = 600
+ client_idle_timeout = 300
# Application-side connection string (example: Python SQLAlchemy)

- DATABASE_URL = "postgresql://appuser:[email protected]:5432/myappdb"
+ DATABASE_URL = "postgresql://appuser:[email protected]:6432/myappdb"
+                "?connect_timeout=5&application_name=myapp"
# Port 6432 = PgBouncer. connect_timeout=5 ensures fast failure and retry.

💡 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.


Firewall / Security Group Rules (AWS/GCP/Azure)

If running on a cloud provider, the silent timeout is almost always a security group or firewall rule:

# AWS Security Group (Terraform)
resource "aws_security_group_rule" "postgres_ingress" {
  type              = "ingress"
  from_port         = 5432
  to_port           = 5432
  protocol          = "tcp"

- cidr_blocks       = ["0.0.0.0/0"]   # NEVER. This is the misconfiguration.
+ source_security_group_id = aws_security_group.app_servers.id  # Restrict to app SG only
}

Prevention in CI/CD

Stop this class of misconfiguration from reaching production:

1. Checkov — Static Analysis on Terraform/CloudFormation

pip install checkov
checkov -d ./terraform --check CKV_AWS_25   # Checks for unrestricted SG ingress on port 5432

Checkov rule CKV_AWS_25 will fail the pipeline if any security group permits 0.0.0.0/0 inbound on database ports.

2. OPA/Conftest Policy for PostgreSQL Config

# policy/postgres.rego
package postgres

deny[msg] {
  input.listen_addresses == "*"
  msg := "DENY: listen_addresses must not be set to '*'. Bind to a specific private interface."
}

deny[msg] {
  input.max_connections > 200
  msg := "DENY: max_connections > 200 without a connection pooler is a saturation risk."
}
conftest test postgresql.conf --policy policy/postgres.rego

3. GitHub Actions — Connectivity Smoke Test in Staging

# .github/workflows/db-smoke-test.yml
- name: PostgreSQL connectivity smoke test
  run: |
    timeout 5 bash -c 'until nc -zv ${{ secrets.DB_HOST }} 5432; do sleep 1; done'
    PGPASSWORD=${{ secrets.DB_PASS }} psql -h ${{ secrets.DB_HOST }} \
      -U appuser -d myappdb -c 'SELECT 1;' --connect-timeout=5

This gate catches firewall misconfigurations and listen_addresses errors before they reach production deployment.

4. Prometheus Alerting on Connection Pool Exhaustion

# prometheus/alerts/postgres.yml
- alert: PgBouncerPoolSaturation
  expr: pgbouncer_pools_server_active_connections / pgbouncer_pools_server_pool_size > 0.85
  for: 2m
  labels:
    severity: warning
  annotations:
    summary: "PgBouncer pool is >85% saturated — connection timeouts imminent"

Alert at 85% saturation, not 100%. By 100% you are already in the timeout storm.

Related Diagnostics

"Part of the Performance Utility Matrix."

View all 219 Performance Tools →