Two AI Migration Plans in a PostgreSQL Terminal
The migration: rename customers.full_name without downtime
I want customers.full_name to become customers.display_name. The database is PostgreSQL, the API runs across several instances, and background workers also update customer records. Deployments overlap. A migration that works on my laptop can still break production while yesterday’s workers are running.
This is where an AI pair programmer earns its place: not by producing SQL faster, but by exposing assumptions before I touch production. Here are two approaches to the same change, compared at each decision point.
First prompt: SQL generation or deployment planning
Approach A starts with: “Write a migration renaming full_name to display_name, including rollback.” The likely result is ALTER TABLE customers RENAME COLUMN full_name TO display_name, plus the reverse operation. It is short, syntactically plausible, and incompatible with application instances still querying full_name.
Approach B starts with deployment constraints: “We use PostgreSQL with overlapping API and worker deployments. Propose an expand-contract migration. Identify locks, compatibility requirements, backfill races, verification queries, and rollback boundaries. Ask about missing schema details before writing SQL.”
I also provide the PostgreSQL version, schema, indexes, approximate table size, deployment process, and representative queries. I leave credentials and customer data out. The assistant should distinguish facts from assumptions, especially whether every writer is under our control.
Schema change: immediate rename or compatible expansion
Approach A changes the schema and expects every caller to change simultaneously. Reversing the rename does not solve mixed application versions; it simply changes which version breaks.
Approach B adds display_name as a nullable column without a default. That avoids rewriting existing rows for this addition, but the ALTER TABLE still needs a lock. I use a short lock timeout and retry deliberately rather than letting the migration wait indefinitely behind a long transaction.
The next application release writes both columns in the same database transaction and reads display_name with full_name as its fallback. Before backfilling, I verify that all writers, including scheduled jobs and administrative scripts, follow that rule. A forgotten old writer can otherwise leave the new column stale.
Backfill: one giant update or bounded transactions
Approach A often follows with one UPDATE across the entire table. On a small development database, that looks harmless. In production, it can generate substantial write-ahead logging, retain row locks until commit, and increase replica lag.
Approach B copies full_name into display_name in primary-key batches, committing each batch. Each update includes a display_name IS NULL predicate so it does not overwrite a value already populated by a concurrent dual-writing request. The assistant drafts the script; I review its transaction boundaries and restart behavior.
- Each batch records its cursor and affected row count.
- The operator pauses when replication lag exceeds our agreed threshold.
- Verification checks missing values and unexpected differences between both columns.
- Null source values receive an explicit policy before enforcing constraints.
I test interruption and restart against a production-shaped staging dataset. An empty local database proves very little about runtime, contention, or recovery.
Review workflow: compare plans, not confident prose
In my editor, I can ask Claude Sonnet 5.5 to draft the staged plan, then ask GPT-6.1 Sol to attack its deployment assumptions. Agreement is not proof; executable tests and observed database behavior remain the gate.
Fluxo makes that comparison convenient through one key and one base URL, https://api.fluxorelay.com, across Claude, GPT, Gemini, DeepSeek, Kimi, GLM, Qwen, Grok, and more. It works with Claude Code, Codex, Gemini CLI, and any OpenAI SDK. Billing follows real tokens, including cache reads and writes, with no monthly fee, so repeated schema-context reviews belong in the cost estimate.
If this fits your terminal workflow, consider creating a Fluxo account. Users also earn a referral share when people they invite pay.
Verdict: expand-contract wins when deployments overlap
The immediate rename wins on line count. The staged plan wins on operational safety. After verification, I switch reads to display_name, retain dual writes through the rollback window, and only later remove full_name. During that window, rollback means returning to a compatible dual-writing release, not resurrecting arbitrary old writers.
My verdict: use AI to draft and challenge an expand-contract plan, never as authorization to execute it. Humans own the deployment order, lock budget, verification evidence, and the moment rollback stops being cheap.