Postgres Error: ECONNREFUSED — Connection Refused
Error: connect ECONNREFUSED 127.0.0.1:5432
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1607:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 5432
}
ECONNREFUSED isn’t a Postgres error — it’s an operating-system error returned to your app’s TCP stack when Postgres (or whatever’s at the other end of your connection string) actively refused the connection. That distinction matters: ECONNREFUSED is debugged from the network layer up, not from inside Postgres.
Why this happens
- Postgres isn't running. The most common cause locally — `postgres` service stopped, container exited, or systemd unit failed. Production: pod evicted, crash-looped, or the standby never promoted after primary failure.
- Wrong host or port in connection string. Pointing at `localhost` from inside a container (where the DB is on the host or in another container), wrong port (default 5432, but Postgres can run on any port), or DNS resolution returning the wrong A record.
- pg_hba.conf only listens on localhost. Default Postgres binds to `127.0.0.1` only. To accept remote connections you also need `listen_addresses = '*'` in `postgresql.conf` AND a matching `host` line in `pg_hba.conf`.
- Firewall, security group, or network ACL blocking. Cloud DBs default to no public ingress. Connecting from outside the VPC needs explicit security-group rules. Local connections can be blocked by `iptables`, `ufw`, or Windows Firewall.
- Connection pool exhausted upstream of Postgres. PgBouncer or RDS Proxy in front of Postgres can refuse connections (sometimes as ECONNREFUSED rather than a clean error) when its pool is saturated. Looks like Postgres is down even though it's healthy.
How to fix it
Fixes are ordered by likelihood. Start with the first one that matches your context.
1. Confirm Postgres is up and listening
Use `pg_isready` (ships with Postgres client tools) to check both the network path and Postgres' internal readiness. It distinguishes "no TCP" (ECONNREFUSED) from "TCP up but Postgres rejecting" (auth/SSL).
# From the host trying to connect:
pg_isready -h db.example.com -p 5432
# /var/run/postgresql:5432 - accepting connections ← good
# localhost:5432 - no response ← ECONNREFUSED
# If pg_isready fails: check Postgres process locally
sudo systemctl status postgresql
sudo ss -tlnp | grep 5432
2. Verify the connection string is what you think it is
Print the resolved DSN (with password redacted) at startup. Misconfigured env vars are responsible for an embarrassing share of ECONNREFUSED reports. Inside Docker, `localhost` means the container itself, not the host — use the service name from compose, or `host.docker.internal` on Mac/Windows Docker Desktop.
import { Pool } from 'pg';
const pool = new Pool({
host: process.env.PGHOST,
port: Number(process.env.PGPORT ?? 5432),
database: process.env.PGDATABASE,
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
});
console.log('postgres connection target:', {
host: process.env.PGHOST,
port: process.env.PGPORT,
database: process.env.PGDATABASE,
user: process.env.PGUSER,
// never log password
});
3. Open `listen_addresses` and `pg_hba.conf` for remote access
Two files, both must change. After editing, `SELECT pg_reload_conf();` or restart Postgres.
listen_addresses = '*' # or specific IPs
port = 5432
4. Open the firewall / security group on port 5432
AWS RDS: edit the DB's security group to allow inbound TCP 5432 from your app's security group. Linux: `sudo ufw allow 5432/tcp` or matching `iptables`. Windows: Windows Defender Firewall → Inbound Rules. Cloud: VPC Network ACLs may also need updating, but rarely.
5. If using PgBouncer, check pool saturation
`SHOW POOLS;` and `SHOW CLIENTS;` against the PgBouncer admin DB. If `cl_waiting` is non-zero and Postgres is healthy, PgBouncer is the bottleneck — increase `default_pool_size` or scale Postgres connection capacity.
Detection and monitoring in production
Health-check against Postgres at the network layer (`pg_isready`) and the SQL layer (`SELECT 1`) separately. Alert on the network check first — that's a different failure (network/host) from the SQL check (auth/permission/lock). Track ECONNREFUSED rate per app instance; a single instance failing while others succeed points at that instance's network rather than Postgres being down.
Related errors
Frequently asked questions
What's the difference between ECONNREFUSED and ETIMEDOUT? +
Why does ECONNREFUSED only happen from my app and not from psql on the DB host? +
I get ECONNREFUSED from inside Docker even though Postgres is running on my Mac. +
My RDS instance returns ECONNREFUSED — is the database down? +
Postgres is on port 5432 but I get ECONNREFUSED. Is something else listening? +
Should I retry on ECONNREFUSED? +
Can a connection pool cause ECONNREFUSED? +
Does ECONNREFUSED indicate a Postgres bug? +
When to escalate to Postgres support
If Postgres logs show clean accept/reject patterns but the network layer is silent, escalate to your network team or cloud provider — that points at SG/NACL/route-table issues. If you're on managed Postgres (RDS, Cloud SQL, Heroku) and the provider's status page shows green but you can't connect, open a support ticket with your DB instance ID and a tcpdump from your app side.
Read more: /guide/database-connection-debugging/