# Workflow: safe migration deploys, direct for migrate, pooled for app

## TL;DR

Migrations never run through the pooler, and never run unrehearsed. CI shows the rehearsal migration and diff on every PR; production deploys log which string the migrator used.

Use this when you run into the situation in the title.

**When not to use this skill:** unrelated tasks. It covers only the procedure above.

## Steps

1. In CI, create a schema-only branch from production.

   Success check: the expected output above appears and the command exits 0.

2. Run the migration against the schema-only branch using the direct connection string.

   Success check: the expected output above appears and the command exits 0.

3. Diff the resulting schema against expectations; fail the pipeline on unexpected diffs.

4. On deploy: run the migration against production using the direct string (`DATABASE_URL_UNPOOLED` / migrate-specific env var).

   Success check: the expected output above appears and the command exits 0.

5. Deploy the app with the pooled string (`DATABASE_URL`).

   Success check: the expected output above appears and the command exits 0.

6. Delete the schema-only branch.

   Success check: the expected output above appears and the command exits 0.

## Compatibility

The steps above apply to the commands named in them. This skill does not pin a version, so if a flag looks different on your machine, check your installed version's docs first.

## Details

# Workflow: safe migration deploys

## Goal

## Ordering constraints

- Migrate before deploying the code that depends on the new schema (expand-then-contract for anything destructive).
- The rehearsal branch must be created from the current production branch, or the rehearsal is fiction.

## Traps

- Running migrations through `-pooler`: PgBouncer transaction mode breaks multi-statement migrations with session state.
- One env var for both: the app gets the direct string "temporarily" and it becomes permanent; keep two vars.
- Destructive migrations (drop column) need the expand/contract pattern regardless of where they run.

## Verify
