Skip to content
Latchkey

Rails "PG::ConnectionBad" During Migrations in CI

ActiveRecord could not establish a connection to Postgres when running db:migrate. The adapter never reached the server - a connectivity or configuration issue, not a migration SQL problem.

What this error means

rails db:migrate (or db:prepare) fails with PG::ConnectionBad / ConnectionNotEstablished, often "could not connect to server" or "Connection refused". It frequently clears on retry once the database service is up.

Rails output
ActiveRecord::ConnectionNotEstablished: connection to server at "127.0.0.1",
port 5432 failed: Connection refused
  Is the server running on that host and accepting TCP/IP connections?
(PG::ConnectionBad)

Common causes

Database service not ready

A Postgres service container is still starting when db:migrate runs, so the connection is refused. This is the most common CI cause and is transient.

Wrong host/port or DATABASE_URL

The database.yml or DATABASE_URL points at a host the runner cannot reach (e.g. localhost vs the service name), so every connection fails.

Transient network blip

A brief connectivity drop between the runner and a remote database can cause an intermittent connection failure that succeeds on retry.

How to fix it

Wait for Postgres before migrating

Block on readiness so the migrate step does not race the database boot.

Terminal
until pg_isready -h "$PGHOST" -p "$PGPORT"; do sleep 1; done
bin/rails db:prepare

Add a service healthcheck

.github/workflows/ci.yml
services:
  postgres:
    image: postgres:16
    env: { POSTGRES_PASSWORD: postgres }
    options: >-
      --health-cmd pg_isready --health-interval 5s --health-retries 10

Verify the connection settings

  1. Confirm DATABASE_URL/database.yml host matches the CI network (service name, not localhost, when using containers).
  2. Check the port is exposed and credentials match the service env.
  3. Retry once dependencies are healthy to confirm a transient failure.

How to prevent it

  • Gate db:migrate on pg_isready or a service healthcheck.
  • Keep DATABASE_URL aligned with the CI network topology.
  • Use db:prepare so a fresh CI database is created and migrated consistently.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →