SaaS architecture
Connection refused: is the PostgreSQL server running?
psql's Connection refused, measured on PostgreSQL 17: what the message means, how it differs from timeouts and DNS errors, and the Docker cases behind it.
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused, followed by Is the server running on that host and accepting TCP/IP connections?, is not a PostgreSQL server error and has no server SQLSTATE: it comes from libpq, the client library, before any server has said a word. The operating system answered the connection attempt with “nothing is listening on this address and port”. The obvious cause is that no server is listening on that port. In Docker setups the server is often running, just at a different address than the one the client uses.
We measured this with psql 10.23 to 18.6 against PostgreSQL 17.11 in the official postgres Docker images, on 22 October 2026. One detail for anyone reproducing it: the postgres:12 image ships libpq 17.2, so its psql prints the new text; we needed postgres:10-alpine (libpq 10) to get the old wording.
What does “Connection refused” mean in psql?
Nothing accepted a TCP connection on that address and port. With no server on port 55528:
psql: error: connection to server at "localhost" (127.0.0.1), port 55528 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
psql 12.22 to 18.6 printed exactly this and exited with code 2. The message comes from libpq, not from psql, and these images ship libpq 17.2 (postgres:12), 18.1 (postgres:13) or 18.6 (14 to 18). Only psql 10.23 with libpq 10 printed the older wording, which you will find in older forum threads; according to the libpq source (fe-connect.c), the wording changed in libpq 14:
psql: 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 55528?
Same meaning. Neither version reached a server, so nothing about users or passwords has been checked yet; errors such as password authentication failed or role does not exist only appear once the connection itself works.
Is it refused, a timeout, or a host name problem?
The word after failed: tells you which. These are the texts we got:
| What we did | Exact message (psql 17.11, libpq 18.6) | What it means |
|---|---|---|
| nothing listening on the port | … port 55528 failed: Connection refused | host reachable, no server on that address and port |
non-routable address, connect_timeout=3 | connection to server at "10.255.255.1", port 5432 failed: timeout expired (after 3.2 s) | no answer at all (we measured a non-routable address); typical causes are a firewall that drops packets or the wrong network |
| unknown host name | could not translate host name "nn6cr-nonexistent-host" to address: Temporary failure in name resolution | DNS: the name does not resolve where the client runs |
no -h, no server in that container | connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory | psql used the Unix socket, and nothing created it |
| port published by Docker, server not accepting yet | … failed: server closed the connection unexpectedly | something accepted the connection and then closed it — in our case the Docker port mapping |
A refusal is a definite answer from the host; a timeout means the packets got no answer at all, so look at the network rather than at PostgreSQL. If the connection does get through but the server is full, you get a server error instead, covered in remaining connection slots are reserved.
Why does the message mention both ::1 and 127.0.0.1?
Because localhost resolved to two addresses and libpq tried both. Inside a regular container, /etc/hosts had both 127.0.0.1 localhost and ::1 localhost, and psql reported each failure:
psql: error: connection to server at "localhost" (::1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
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?
psql 10.23 did the same in its old wording. The PostgreSQL documentation describes this: when “a single host name is translated to multiple addresses, all the hosts and addresses will be tried in order, until one succeeds”. Two lines are one problem, reported per address. On our host, where localhost maps only to 127.0.0.1, there was one line.
Why is the connection refused when PostgreSQL runs in Docker?
Because the server is reachable at a different address than the one the client uses. We measured four setups:
- No
-p. Apostgres:17container without a published port was running and healthy, but nothing listened on the host port. From the host, only the container’s own bridge IP (172.17.0.3:5432) answered. -p 127.0.0.1:55525:5432. Worked from the host, both as127.0.0.1and aslocalhost.- From another container, with
localhost. Refused on::1and127.0.0.1, on 5432 and on the published 55525 alike: inside a container,localhostis that container itself. With the server’s container name on a shared user-defined network (-h nn6cr-pub -p 5432) it worked. The published port 55525 was refused there: containers talk to each other on the container port. On the default bridge network the name did not even resolve:could not translate host name "nn6cr-pub" to address. - Right after
docker run. We polled every ~50 ms from before the container started. The first attempts were refused; once Docker had published the port, one attempt gotserver closed the connection unexpectedly, and the first successful query came about 1.2 s afterdocker run. In 148 logged attempts we did not seethe database system is starting up: the image’s initialisation server listened only on the Unix socket, according to its log. Code that connects at startup should retry both refusals and closed connections for a few seconds.
Can listen_addresses cause Connection refused?
Yes. listen_addresses decides which interfaces the server listens on, and according to the documentation its default is localhost, “which allows only local TCP/IP ‘loopback’ connections to be made”. The official Docker image sets it to * — show listen_addresses returned * in our container — which is why the Docker cases above worked at all.
We started a container with -c listen_addresses=localhost and -p 127.0.0.1:55526:5432. The log said listening on IPv6 address "::1" and listening on IPv4 address "127.0.0.1", and inside the container psql -h localhost worked. From outside:
-- from the host, through the published port:
psql: error: connection to server at "127.0.0.1", port 55526 failed: server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
-- from the host, to the container's own IP:
psql: error: connection to server at "172.17.0.4", port 5432 failed: Connection refused
So through Docker’s port mapping this misconfiguration does not even say “refused”: Docker’s proxy process (docker-proxy) accepts the connection on the host port, cannot reach the server on the container’s address, and closes it. A client that connected to the container’s own address got the plain refusal; set listen_addresses to the address the clients reach, and allow them in pg_hba.conf. For the full list of codes a server does send once you are connected, see our measured SQLSTATE overview.
What we did not measure
The SQLSTATE that drivers attach to this client-side failure (we had no driver such as psycopg installed). the database system is starting up (57P03), which we did not trigger. Docker Desktop on macOS and Windows, firewalls that reject rather than drop, Windows and macOS installers, and pgAdmin or DBeaver — which connect over the same TCP mechanism, so when they run in a container, localhost is that container, not the database.
Sources: PostgreSQL 17 documentation on connection settings (listen_addresses) and libpq connection strings (multiple addresses), read on 22 October 2026, and the libpq source (src/interfaces/libpq/fe-connect.c in the PostgreSQL repository, branches REL_13_STABLE and REL_14_STABLE, read on the same day). All measurements are our own, on PostgreSQL 17.11 and psql 10.23–18.6 with libpq 10, 17.2, 18.1 and 18.6 in containers, on 22 October 2026.