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
mainwithout having run against Neon behind Hyperdrive.
Decision
Split them.
- Locally: Docker Compose Postgres with
pg_trgmand FTS configured, defined inpackages/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.