Skip to content

fix(db): make deploy's dry-run clone schema-only by default - #55

Open
nipunappri[bot] wants to merge 1 commit into
mainfrom
fix/deploy-schema-only-clone
Open

nipunappri[bot] wants to merge 1 commit into
mainfrom
fix/deploy-schema-only-clone

Conversation

@nipunappri

@nipunappri nipunappri Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Branch: fix/deploy-schema-only-clone → main

Summary

  • postkit db deploy cloned the entire target database, including every row, into a throwaway local container before running its DDL dry-run — then dropped it. On any database with real data this dominated the command's runtime.
  • The dry-run verifies that committed DDL applies cleanly, which only needs the target's structure. The clone is now pg_dump --schema-only by default.
  • Added --with-data to opt back in for migrations whose risk lives in the data rather than the schema.

Changes

  • db deploy clones structure only by default. deploy.ts now passes schemaOnly: !options.withData to both clone paths (host and docker exec). Previously it passed nothing and inherited the = false default, while db start correctly passed true.
  • Added --with-data to db deploy (modules/db/index.ts) for cases where the migration's risk is in the data: adding NOT NULL or UNIQUE to a populated column, type narrowing, backfills.
  • Made schemaOnly a required parameter on cloneDatabase and cloneDatabaseViaContainer. The silent default is exactly how this bug happened — one caller remembered, one didn't. Requiring it means no future caller can pull row data by omission. Typechecking confirmed start and deploy were the only production callers.
  • Warn on --with-data that seeds run as part of the dry-run against a clone that already holds the target's rows, so seed inserts may conflict on existing keys.
  • Clone progress messages now state which mode is running ("no row data" / "with row data") so the cost is visible rather than inferred from how long it hangs.
  • Docs (cli/docs/db.md, CLAUDE.md) updated — the old behavior was documented as deliberate, so those passages needed rewriting, not just extending.

Type of Change

  • fix: Bug fix

Test Plan

  • Unit tests pass (npm run test) — 382 passed, 31 files
  • Build succeeds (npm run build)
  • Typecheck clean (npx tsc --noEmit)
  • Added smoke test asserting db deploy --help documents --with-data as opt-in
  • Updated service-level tests that asserted the old implicit default; the explicit schemaOnly: true / false argument paths are both still covered
  • E2E tests (npm run test:e2e) — not run locally (needs Docker/testcontainers); please confirm in CI
  • Manually verified against a remote with a non-trivial dataset — worth one reviewer pass before merge

Breaking Changes

  • Behavior change, not an API break. postkit db deploy no longer clones the target's row data during its dry-run.

cli/docs/db.md previously documented the full-data clone as intentional — "it still clones full data, since it's specifically verifying real migrations against realistic data before they touch production." That rationale is real, so the capability is preserved behind --with-data rather than removed.

The trade-off: a migration that would only fail against real rows (e.g. ALTER COLUMN ... SET NOT NULL on a column containing nulls) will now pass the dry-run and fail on the target instead. Anyone relying on the old behavior should add --with-data to their deploy invocation. Worth calling out in release notes.

The public signatures of cloneDatabase / cloneDatabaseViaContainer gained a required parameter. Both are internal to the CLI, so this only affects in-repo callers.

@Yasirunet
Yasirunet self-requested a review September 24, 2026 12:20
`db deploy` cloned the full target database — schema and every row — into a
throwaway local container before running its DDL dry-run, then dropped it. On
any database with real data this dominated the command's runtime, billed egress
on every deploy, and put production rows on developer machines.

The dry-run verifies that committed DDL applies cleanly, which only needs the
target's structure. Default to `pg_dump --schema-only` and add `--with-data`
for migrations whose risk lives in the data (adding NOT NULL or UNIQUE to a
populated column, type narrowing, backfills).

`schemaOnly` is now a required parameter on `cloneDatabase` and
`cloneDatabaseViaContainer`. The silent `= false` default is how this happened:
`db start` remembered to pass `true`, `db deploy` did not. Requiring it means
no future caller can get row data by omission.

Also warn when `--with-data` is used that seeds run against a clone already
holding the target's rows and may conflict on existing keys.
@nipunappri
nipunappri Bot force-pushed the fix/deploy-schema-only-clone branch from b47f0f2 to 6a94bda Compare September 24, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant