Skip to content
Latchkey

How to Spin Up a Postgres Service for Tests in GitHub Actions

A Postgres service container runs as a sidecar your job reaches over localhost:5432, so tests hit a real database instead of a mock.

Declare postgres under services: with the official postgres image, set POSTGRES_PASSWORD, map port 5432, and add a pg_isready health check so steps wait until the server accepts connections.

Steps

  • Add a services.postgres block with image: postgres:16.
  • Set env.POSTGRES_PASSWORD (and optionally POSTGRES_DB).
  • Map ports: [5432:5432] and add a pg_isready health check.
  • Point your test DATABASE_URL at localhost:5432.

Workflow

.github/workflows/ci.yml
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: app_test
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U postgres"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    env:
      DATABASE_URL: postgres://postgres:postgres@localhost:5432/app_test
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

Gotchas

  • Without a health check, the job can start before Postgres accepts connections and tests fail with connection refused.
  • When the job itself runs in a container, connect by the service name postgres, not localhost.

Related guides

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