How to Fix "Could Not Connect to Server: Connection Refused" in psql
Quick answer
Running psql fails before you even get to a login prompt, with the connection actively refused rather than timing out or asking for a password. This means...
Running psql fails before you even get to a login prompt, with the connection actively refused rather than timing out or asking for a password. This means either PostgreSQL isn't running at all, or it's running but not listening on the address and port you're trying to reach.
The Problem
A basic connection attempt fails immediately:
$ psql -U app_user -d mydb -h localhost
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
Trying a remote host produces a similar message, though the underlying cause is often different:
$ psql -U app_user -d mydb -h 203.0.113.10
psql: error: connection to server at "203.0.113.10", port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
Why It Happens
"Connection refused" is a specific TCP-level response meaning something actively rejected the connection β no service was listening on that port, as opposed to a timeout, which usually means a firewall silently dropped the packets. This distinction is a useful diagnostic clue on its own. Common causes:
- PostgreSQL isn't running at all β the service crashed, was never started, or failed during startup.
- PostgreSQL is running but only listening locally β the default
listen_addressessetting is oftenlocalhostonly, which refuses any connection arriving from outside the machine itself, even if the service is healthy. - Wrong port β a non-default PostgreSQL installation, or multiple PostgreSQL versions on the same machine, listening on a port other than the standard 5432.
- A firewall is blocking the port for remote connections β though this typically produces a timeout rather than an immediate refusal, some firewall configurations do actively reject rather than silently drop.
The Fix
First, confirm PostgreSQL is actually running on the target machine:
sudo systemctl status postgresql
If it's not active, start it and check the logs for why it might have failed previously:
sudo systemctl start postgresql
sudo journalctl -u postgresql --since "10 minutes ago"
If it's running but you're connecting from a different machine, check what address it's actually listening on:
sudo -u postgres psql -c "SHOW listen_addresses;"
listen_addresses
-------------------
localhost
A value of localhost means only local connections are accepted. For remote access, change it to listen on all interfaces (or a specific one) in postgresql.conf:
listen_addresses = '*'
This requires a full restart to take effect:
sudo systemctl restart postgresql
Changing listen_addresses alone isn't enough β you also need to explicitly allow the connecting host in pg_hba.conf, or PostgreSQL will still reject the connection even though it's now technically listening:
host mydb app_user 203.0.113.0/24 scram-sha-256
Reload PostgreSQL after editing pg_hba.conf (a reload is sufficient, no restart needed for this file):
sudo systemctl reload postgresql
Confirm the port PostgreSQL is actually bound to matches what you're connecting on:
sudo ss -tlnp | grep postgres
LISTEN 0 244 0.0.0.0:5432 0.0.0.0:* users:(("postgres",pid=1234,fd=6))
Still Not Working?
If PostgreSQL is confirmed running and listening on the right interface but remote connections still fail, check the firewall on the server itself, since that's a completely separate layer from PostgreSQL's own configuration:
sudo ufw status
sudo ufw allow from 203.0.113.0/24 to any port 5432
If you're connecting to a managed cloud database (AWS RDS, Google Cloud SQL, etc.), check the provider's own network security configuration β security groups, VPC firewall rules, or authorized networks β since these operate entirely outside PostgreSQL's own settings and are a very common cause of this exact error for cloud-hosted databases specifically.
It's also worth distinguishing between "connection refused" and a plain timeout, since they point at different layers of the problem and knowing which one you're seeing saves significant debugging time. A refused connection, as covered above, means a TCP packet reached the target machine and something there actively rejected it β this points at PostgreSQL itself (not running, or not listening on that interface). A timeout, by contrast, means your connection attempt never got a response at all, which usually points at a network-level block further upstream β a firewall silently dropping packets, a security group rule, or a routing issue preventing the packet from ever reaching the target machine in the first place:
# Refused: PostgreSQL is reachable but rejecting
psql: error: connection to server at "203.0.113.10", port 5432 failed: Connection refused
# Timeout: something between you and the server is silently blocking traffic
psql: error: connection to server at "203.0.113.10", port 5432 failed: Connection timed out
If you're seeing a timeout rather than a refusal, focus your investigation on network-level rules (security groups, firewalls, routing) rather than PostgreSQL's own configuration, since PostgreSQL never even had the chance to accept or reject the connection in that scenario.