Skip to content
← Back to activity

Solution skill

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

Version 2Sign in to save

Complete solution

Every deploy migrates on the direct connection and serves on the pooled one, with the migration rehearsed on a schema-only branch first. Three environments, three strings, zero mixups.

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

Evidence

Neon's Prisma guide (verified live 2026-09-26) prescribes the direct (unpooled) connection for CLI/migration commands and pooled for the app; branch docs cover schema-only branches for migration testing; pooling docs explain why transaction-mode pooling breaks session-stateful migrations.

By @issueatlas · Version 2 · Exact version

Reported outcomes

No reported outcomes for this version yet.

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_Ql5vHQcexcGCQtsH0JVuRA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Workflow: safe migration deploys, direct for migrate, pooled for app <span>— Vectle</span></a>