Deploy Error Decoder

ECONNREFUSED: connection refused — how to fix it

Quick answer: ECONNREFUSED means your app reached the host but nothing was listening on that port — the connection was actively refused. The dependency (Postgres, Redis, an internal API) is down, not started yet, on a different host/port, or unreachable through the network. Verify the service is up and listening, confirm the host and port your app is using, and inside Docker use the service name — not localhost.

What the error looks like

The address in the message tells you exactly what your app failed to reach:

Error: connect ECONNREFUSED 127.0.0.1:5432
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1494:16)
  errno: -111, code: 'ECONNREFUSED', address: '127.0.0.1', port: 5432

:5432 is Postgres, :6379 is Redis, :3306 is MySQL. "Refused" is different from "timed out": refused means something answered "nothing's here on this port." That's a strong clue — the host is reachable, the service isn't.

Why connections get refused

The service is down

The database or upstream isn't running — crashed, never started, or still booting when your app connected.

Wrong host or port

A typo, a missing env var defaulting to localhost, or pointing at the wrong port for that service.

localhost inside a container

In Docker, localhost means the container itself — not the host or another container. Use the compose service name.

Bound to the wrong interface

The service listens only on 127.0.0.1, so connections from other hosts/containers are refused. Bind 0.0.0.0.

Diagnose it in three steps

1

Is anything listening on that port?

# On the host the service should be running on
ss -ltnp | grep 5432
# Probe it directly from where your app runs
nc -zv 127.0.0.1 5432
2

Confirm the host and port your app uses

# Print the actual values your app resolved at runtime
echo "$DATABASE_URL"
# A wrong env var is the #1 cause — don't trust the config file, check the runtime.
3

In Docker, use the service name

Containers talk to each other by service name on the compose network, not localhost:

# docker-compose.yml — app connects to host "db", not "localhost"
services:
  app:
    environment:
      DATABASE_URL: postgres://user:pass@db:5432/app
  db:
    image: postgres:16
The real fix

Don't start the app before its dependencies

If ECONNREFUSED only happens at startup and then clears, your app raced ahead of its database. Two durable fixes:

  • Wait for the dependency to be healthy before starting — a depends_on with a healthcheck, or a wait-for script.
  • Retry with backoff in your connection code, so a brief dependency restart doesn't take your app down with it.
# compose: gate app start on db actually being ready
services:
  app:
    depends_on:
      db: { condition: service_healthy }
  db:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 5s
      retries: 5
How Infraveil handles this

Ordered startup and dependency health, built in

Infraveil is a backend operations control plane that runs on your own servers. Its agent health-checks your services and coordinates how they start, so an app doesn't go live before the database it depends on is ready — the exact race that produces a startup ECONNREFUSED. When a dependency fails, recovery is gated behind your approval and recorded, and you see every service's status in one place instead of SSHing around to find what's down.

Health checks confirm dependencies are ready before traffic flows
Crashed services are restarted and surfaced in one status view
Recovery actions are approval-gated and recorded, on servers you control

Frequently asked questions

What does ECONNREFUSED mean?

Your app reached the host but nothing accepted the connection on that port — it was actively refused. Usually the target service is down, not started yet, or on a different host/port.

ECONNREFUSED vs ETIMEDOUT — what's the difference?

Refused means something answered "nothing is listening here" (host reachable, service not). Timed out means no answer at all — often a firewall, wrong host, or network issue silently dropping packets.

Why does ECONNREFUSED happen in Docker?

Inside a container, localhost refers to that container, not the host or other containers. Connect using the compose service name (e.g. db:5432) on the shared network instead.

How do I fix ECONNREFUSED only on startup?

Your app started before its dependency was ready. Gate startup on a dependency healthcheck (depends_on: condition: service_healthy) and add retry-with-backoff to your connection code.