Skip to content
Latchkey

Ecto "connection refused" to Postgres in CI

Ecto could not open a TCP connection to Postgres. In CI this almost always means no database service container was started, or the app pointed at the wrong host or port.

What this error means

mix ecto.create or the first query fails with "** (Postgrex.Error) ... connection refused" / "econnrefused" against localhost:5432.

** (DBConnection.ConnectionError)
** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused
- :econnrefused

Common causes

No Postgres service container in the job

GitHub-hosted runners do not run Postgres by default. Without a services: block, nothing listens on 5432.

Wrong host, port, or unhealthy service

The config points at the wrong host (or the service was not health-checked ready), so the connection is refused.

How to fix it

Start a Postgres service with a health check

  1. Add a services: postgres block with a health check so the job waits until it is ready.
  2. Point the test config at localhost:5432 with the service credentials.
  3. Run ecto.create then tests.
.github/workflows/ci.yml
services:
  postgres:
    image: postgres:16
    env:
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432
    options: >-
      --health-cmd pg_isready --health-interval 10s
      --health-timeout 5s --health-retries 5

Match config to the service

Ensure the test repo config uses the same host, port, and credentials as the service container.

config/test.exs
config :my_app, MyApp.Repo,
  hostname: "localhost",
  username: "postgres",
  password: "postgres",
  database: "my_app_test"

How to prevent it

  • Add a health-checked Postgres service for DB-backed tests.
  • Keep test.exs host/port/credentials aligned with the service.
  • Fail fast with pg_isready before running migrations.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →