What happened
Your app just blew up with:
Error: connect ECONNREFUSED 127.0.0.1:5432
ECONNREFUSED means the OS knocked on that port and got the door slammed in its face. Not a timeout. Not a firewall drop. An active refusal β nothing is listening on that port.
The port number tells you which service ghosted you: 5432 = PostgreSQL, 3306 = MySQL, 6379 = Redis, 27017 = MongoDB. Same root cause for all of them β the service isn't running, or your app is pointing at the wrong address.
Debug process
Step 1 β Is the service actually running?
Nine times out of ten, this is it. Start here before touching anything else.
# Linux / macOS
sudo systemctl status postgresql
sudo systemctl status mysql
sudo systemctl status redis
# Or check what's actually listening on that port
sudo ss -tlnp | grep 5432
sudo lsof -i :5432
No output for that port? The service is down. Jump to Fix 1 below.
Step 2 β Is it listening on the right interface?
Trickier than it sounds. PostgreSQL can be running fine but only bound to 127.0.0.1 β which means it rejects anything that doesn't come from localhost.
sudo ss -tlnp | grep 5432
# Expected output:
# LISTEN 0 128 127.0.0.1:5432 0.0.0.0:*
0.0.0.0:5432 or :::5432 means it accepts connections on all interfaces. Only 127.0.0.1:5432? Remote connections are dead on arrival β local only.
Step 3 β Check the connection string in your app
Typos happen. A single wrong character in DB_HOST or DB_PORT sends every connection attempt to a black hole.
# Node.js β check your .env or config file
DB_HOST=localhost
DB_PORT=5432
# Python SQLAlchemy
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
One thing people miss: does localhost actually resolve to 127.0.0.1 on this machine?
ping localhost
# Should resolve to 127.0.0.1 or ::1
On WSL2 or Docker, localhost often resolves differently than you expect β it's bitten plenty of developers.
Step 4 β Docker? The network is probably the issue
Inside a Docker container, localhost is the container itself β not your laptop, not your VM. Your database on the host machine is unreachable via that address.
# Linux β use the Docker bridge gateway IP
DB_HOST=172.17.0.1
# Docker Desktop on Mac or Windows β this just works
DB_HOST=host.docker.internal
Two containers that need to talk? Put them on the same named Docker network and use the container name as the hostname. Don't rely on IP addresses β they change on restart.
Fixes
Fix 1 β Start the service
# PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql # auto-start on boot
# MySQL / MariaDB
sudo systemctl start mysql
# Redis
sudo systemctl start redis
After starting, confirm it actually came up:
sudo ss -tlnp | grep 5432
Fix 2 β Service crashed on start, check the logs
systemctl start can fail silently β the command returns with no error, but the service dies within seconds. The logs will tell you why.
journalctl -u postgresql -n 50 --no-pager
# Look for: permission errors, port conflicts, config syntax errors
Three usual suspects: disk is full (run df -h), wrong ownership on the data directory (/var/lib/postgresql/), or another process already grabbed port 5432.
# Find what's squatting on your port
sudo lsof -i :5432
Fix 3 β Change the bind address for remote connections
For PostgreSQL, find and edit postgresql.conf:
# Find where the config file lives
psql -U postgres -c 'SHOW config_file;'
# Then change this line:
listen_addresses = '*' # was: 'localhost'
Don't forget to also update pg_hba.conf to whitelist the remote host, then restart:
sudo systemctl restart postgresql
For MySQL, the setting lives in /etc/mysql/mysql.conf.d/mysqld.cnf:
bind-address = 0.0.0.0 # was: 127.0.0.1
Fix 4 β Environment variables not loaded
Classic timing problem: the app launches before .env is sourced, falls back to defaults like localhost:5432, and connects to nothing. Print what the app actually sees at runtime:
# Node.js
console.log('DB:', process.env.DB_HOST, process.env.DB_PORT);
# Python
import os
print(os.getenv('DB_HOST'), os.getenv('DB_PORT'))
Seeing undefined or None? The env file isn't being loaded β check your dotenv setup or how the process is being started.
Verification
Before restarting your app, do a raw TCP test to confirm the port is actually reachable:
# Test TCP connectivity directly
nc -zv 127.0.0.1 5432
# Success: Connection to 127.0.0.1 5432 port [tcp/postgresql] succeeded!
# Alternative with curl
curl -v telnet://127.0.0.1:5432
That succeeds but your app still fails? The problem is in the app's config, not the service. Go back to Step 3.
Tips
Debugging Docker bridge networks or VPN routing and staring at an IP you don't recognize? The Subnet Calculator on ToolCraft lets you quickly check which network range an IP belongs to β useful for confirming whether an address is local or getting routed somewhere unexpected.
Lessons learned
- ECONNREFUSED = nothing listening. Debug the service first, not your app code.
- Run
ss -tlnporlsof -i :PORTbefore touching anything. Two seconds, saves twenty minutes. - Docker's
localhosttrap catches everyone at least once βhost.docker.internalis the fix on Mac and Windows. - Add a startup health check so your app waits for the database instead of crashing on boot. Tools like wait-for-it handle this in one line.
- Run
systemctl enableon every database service. A server reboot shouldn't mean chasing this error all over again.

