Initializing Enclave...

How to Fix PostgreSQL 'Connection Refused' on localhost Port 5432

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

TL;DR

  • What broke: PostgreSQL is either not running, not listening on 127.0.0.1:5432, or pg_hba.conf is rejecting the connection before it starts.
  • How to fix it: Confirm the service is active, verify listen_addresses in postgresql.conf, and check pg_hba.conf allows the connecting user/host.
  • Use our Client-Side Sandbox below to paste your postgresql.conf or connection string and auto-generate the corrected config — no data leaves your browser.

The Incident (What Does This Error Mean?)

could not connect to server: Connection refused
        Is the server running on host "localhost" (127.0.0.1) and accepting
        TCP/IP connections on port 5432?

This is a TCP-layer rejection — the OS itself is refusing the connection. The PostgreSQL process either isn't running, is listening on a Unix socket only (not TCP), or is bound to a different interface. Your application is dead in the water. Every query, migration, and health check is failing right now.


The Attack Vector / Blast Radius

This is a full application outage scenario, not a degraded state. Cascading failures include:

  • Connection pool exhaustion: App servers keep retrying, spawning threads that never resolve, eventually OOM-killing the app process.
  • Data integrity risk: If this hit mid-transaction during a deployment or failover, uncommitted transactions may have been lost.
  • Monitoring blind spots: Many APM tools report this as an app-layer 500, masking the real infrastructure root cause and delaying MTTR.
  • Secondary services: Any service depending on this DB (auth, billing, queues) fails silently or loudly depending on circuit breaker configuration.

If this is a shared database host, every tenant/application on it is affected simultaneously.


How to Fix It

Step 1 — Confirm PostgreSQL is Actually Running

# systemd
sudo systemctl status postgresql

# or for versioned installs
sudo systemctl status postgresql@14-main

# If stopped:
sudo systemctl start postgresql

If the service fails to start, check logs immediately:

sudo journalctl -u postgresql --since "10 minutes ago"
# or
tail -100 /var/log/postgresql/postgresql-14-main.log

Step 2 — Confirm It's Listening on TCP Port 5432

sudo ss -tlnp | grep 5432
# Expected output:
# LISTEN  0  128  127.0.0.1:5432  0.0.0.0:*  users:(("postgres",pid=1234,fd=5))

If you see nothing, PostgreSQL is running but bound to a Unix socket only.

Basic Fix — Enable TCP Listening in postgresql.conf

# /etc/postgresql/14/main/postgresql.conf

- listen_addresses = ''
+ listen_addresses = 'localhost'

# For remote access (use with firewall rules):
+ listen_addresses = '*'

After editing:

sudo systemctl restart postgresql

Step 3 — Verify pg_hba.conf Allows the Connection

# /etc/postgresql/14/main/pg_hba.conf

# Bad: no entry for local TCP connections
- local   all   all                peer

# Good: allow local TCP connections with password auth
+ host    all   all   127.0.0.1/32  scram-sha-256
+ host    all   all   ::1/128        scram-sha-256

Reload after pg_hba.conf changes (no full restart needed):

sudo systemctl reload postgresql
# or inside psql:
SELECT pg_reload_conf();

Enterprise Best Practice — Dockerized / Kubernetes Environments

If running in Docker, the most common cause is the container not being ready when the app starts:

# docker-compose.yml

services:
  app:
    depends_on:
-     - postgres
+     - postgres
+   condition: service_healthy

  postgres:
    image: postgres:15
+   healthcheck:
+     test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
+     interval: 5s
+     timeout: 5s
+     retries: 10

For Kubernetes, ensure the Service targetPort matches the container port and the pod is Running/Ready:

kubectl get pods -l app=postgres
kubectl describe svc postgres-service
kubectl exec -it <app-pod> -- pg_isready -h postgres-service -p 5432

💡 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. Add pg_isready to your deployment health gates:

# In your deploy script or GitHub Actions step
until pg_isready -h $DB_HOST -p 5432 -U $DB_USER; do
  echo "Waiting for PostgreSQL..."
  sleep 2
done

2. Checkov / Terraform — enforce listen_addresses is not wildcard without firewall:

# If using RDS or Cloud SQL, enforce VPC-only access
resource "aws_db_instance" "postgres" {
  publicly_accessible = false  # Checkov: CKV_AWS_17
}

3. Integration test your DB connection in CI before deploying:

# .github/workflows/ci.yml
services:
  postgres:
    image: postgres:15
    env:
      POSTGRES_PASSWORD: testpass
    options: >-
      --health-cmd pg_isready
      --health-interval 5s
      --health-timeout 5s
      --health-retries 10

4. OPA Policy — flag any app deployment missing a DB readiness probe in Kubernetes:

deny[msg] {
  input.kind == "Deployment"
  container := input.spec.template.spec.containers[_]
  not container.readinessProbe
  msg := sprintf("Container '%v' is missing a readinessProbe — DB race condition risk.", [container.name])
}

Related Diagnostics

"Part of the Performance Utility Matrix."

View all 219 Performance Tools →