How to Fix Postgres Connection Refused on the Wrong Port
connection refused from Postgres means nothing is accepting connections at the host and port you dialed - usually Postgres isn't running, is listening on a different port or interface, or a firewall is blocking it. The most common config cause is a port that drifted in postgresql.conf while the app still dials 5432 - here's how to find and fix it.
Why this happens
PostgreSQL's listening port is set by a single directive in postgresql.conf. When a DBA
changes it - say, to avoid a conflict or follow a new internal standard - the server
restarts on the new port. Every client still dialing 5432 immediately gets:
FATAL: connection refused (port 5432)
psycopg2.OperationalError: could not connect to server
The database is healthy. The problem is both sides are not using the same number.
Step 1: confirm which port postgres is actually using
pg_isready # uses default 5432 - will fail
grep ^port /etc/postgresql/16/main/postgresql.conf # shows the real port
If the output is port = 5433, that's the mismatch. You can also confirm with:
ss -ltnp | grep postgres
The LISTEN line shows the real bound port.
Step 2: fix the mismatch
You have two options - move postgres back to 5432, or update the app's connection string.
Option A - revert postgresql.conf to 5432:
# Edit /etc/postgresql/16/main/postgresql.conf
# Change: port = 5433
# To: port = 5432
pg_ctlcluster 16 main restart
pg_isready # should return :5432 - accepting connections
Option B - update the app to use the new port:
# In app.py or your connection config
conn = psycopg2.connect(
host="localhost",
port=5433, # match whatever postgresql.conf declares
dbname="userdir",
user="postgres",
)
Option A is usually right during incident recovery - reverting to a known-good default is faster and unblocks every other client simultaneously. Option B is the long-term answer when you intentionally want a non-default port.
Step 3: verify the app connects
After restarting postgres (or updating the app), confirm end-to-end:
psql -h localhost -U postgres -d userdir -c "SELECT 1;"
curl http://localhost:8080/health
If the psql command succeeds but the app still fails, check the app's own connection string - it may have the port hardcoded in a config file separate from the one you just edited.
Other common causes of "connection refused"
A drifted port is the focus above, but the same connection refused has a few
other usual causes - all meaning "nothing is accepting at this host:port":
- Postgres isn't running - start it:
pg_ctlcluster 16 main start(orsystemctl start postgresql), thenpg_isready. - Listening only on localhost -
listen_addressesin postgresql.conf islocalhostbut you're connecting from another host/container; set it to'*'(or the right IP) and restart. - A firewall blocks the port - open 5432 (or your port) between client and server.
- Wrong host - you're dialing
localhostbut postgres runs on another machine, container, or network namespace.
(Note: an auth rejection gives a different error - no pg_hba.conf entry or
password authentication failed - not connection refused.)
Key takeaway
Port mismatches are silent until something restarts. Production avoids this by parameterizing the port through an environment variable or a service-discovery layer (like a Kubernetes Service), so no app code ever has a hardcoded port number to drift out of sync with the database config.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Using pg_isready and grep to identify a port mismatch in postgresql.conf
- Restarting PostgreSQL with pg_ctlcluster after a config change
- Choosing between reverting the server port vs updating the app connection string
FAQ
Why does PostgreSQL say "connection refused"?
Connection refused means nothing is accepting connections at the host and port you dialed. The usual causes are Postgres isn't running, it's listening on a different port (a drifted port in postgresql.conf), it's only listening on localhost (listen_addresses), or a firewall is blocking the port. It is not an auth error - that gives a different message.
How to fix "connection to server at localhost port 5432 failed: connection refused"?
Confirm Postgres is running (pg_isready / pg_ctlcluster 16 main status), check the real port with grep ^port /etc/postgresql/16/main/postgresql.conf, make sure listen_addresses includes the interface you connect from, then restart and retry psql -h localhost -p 5432 -U postgres.
How do I check if port 5432 is open?
On the server, ss -ltnp | grep 5432 shows whether anything is listening; from the client, nc -zv localhost 5432 tests reachability; and pg_isready -h localhost -p 5432 checks Postgres specifically.
How do I check which port PostgreSQL is listening on?
Run grep ^port /etc/postgresql/16/main/postgresql.conf for the configured port and ss -ltnp | grep postgres for the port the kernel actually has it bound to - together they show config vs reality.
Do I need to restart PostgreSQL after changing the port?
Yes - a reload is not enough for a port change. Run pg_ctlcluster 16 main restart (Debian/Ubuntu) or systemctl restart postgresql, then confirm with pg_isready.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →