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, orpg_hba.confis rejecting the connection before it starts. - How to fix it: Confirm the service is active, verify
listen_addressesinpostgresql.conf, and checkpg_hba.confallows the connecting user/host. - Use our Client-Side Sandbox below to paste your
postgresql.confor 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])
}