Now-Next

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.

Chris van Eijk, Now-Next · · 7 min read

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 didExact message (psql 17.11, libpq 18.6)What it means
nothing listening on the port… port 55528 failed: Connection refusedhost reachable, no server on that address and port
non-routable address, connect_timeout=3connection 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 namecould not translate host name "nn6cr-nonexistent-host" to address: Temporary failure in name resolutionDNS: the name does not resolve where the client runs
no -h, no server in that containerconnection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directorypsql used the Unix socket, and nothing created it
port published by Docker, server not accepting yet… failed: server closed the connection unexpectedlysomething 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. A postgres:17 container 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 as 127.0.0.1 and as localhost.
  • From another container, with localhost. Refused on ::1 and 127.0.0.1, on 5432 and on the published 55525 alike: inside a container, localhost is 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 got server closed the connection unexpectedly, and the first successful query came about 1.2 s after docker run. In 148 logged attempts we did not see the 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.

Let's talk

What are we building?

One conversation is enough to know whether we fit. Tell us what you have in mind — we will tell you how fast it can happen, and whether we are the right people for it.

Start the conversation