Skip to content

ADR-0011: Docker Postgres locally, Neon branch in CI

ADR-0011: Docker Postgres locally, Neon branch in CI

  • Status: Accepted
  • Date: 2026-07-30
  • Supersedes:
  • Superseded by:

Context

ADR-0003 means tests need a real Postgres with real extensions — pg_trgm and FTS cannot be mocked meaningfully. Two competing needs:

  • Agents need a fast inner loop. The delivery loop (docs/standards/the-loop.md) runs the gate repeatedly. If every run needs network and credentials, iteration is slow and flaky, and a network blip reads as a test failure.
  • The merge gate needs realism. Nothing should reach main without having run against Neon behind Hyperdrive.

Decision

Split them.

  • Locally: Docker Compose Postgres with pg_trgm and FTS configured, defined in packages/db. No credentials, no network.
  • In CI: an ephemeral Neon branch per pull request, torn down after the run.

Rationale

Each environment gets the property it actually needs. The local loop is fast and offline; the gate is real. Neon’s branching makes the CI half cheap — a branch is a copy-on-write fork of the database, not a fresh provision.

Consequences

  • The Docker Postgres version and extension set must track Neon’s. A mismatch here is a silent parity bug; pin the version and note it in packages/db.
  • Neon free-tier branch counts are limited, so branches are CI only — never the local loop — and CI must tear them down even on failure.
  • CI needs a Neon API token in repository secrets (WI-H04, human-provisioned).
  • Migrations are exercised twice per work item: locally on every gate run, and against a fresh Neon branch at PR time.

Alternatives considered

Neon branch per PR only. Maximum realism, no Docker dependency. Rejected: every local run needs network and credentials, and it burns branch quota on the inner loop.

Docker only. Fast and fully offline. Rejected: nothing exercises Hyperdrive or Neon’s real behaviour until production does.