Why an AI Coding Agent Re-Runs a Finished Migration
An AI coding agent that can't see your migration history will happily rewrite a schema change that already ran. Here is the fix.
Why an AI Coding Agent Re-Runs a Finished Migration
An AI coding agent re-runs a database migration that already ran when it cannot see the migration history the way your framework's own tooling can, so it treats a schema change as new work instead of a completed one. The fix is making the agent check applied-migration state before it writes a new migration, not just before it writes new code.
How this actually happens
Migration tools like Prisma, Rails, Django, and Alembic track which migrations have run in a dedicated table (`_prisma_migrations`, `schema_migrations`, `django_migrations`) separate from your application schema. An AI coding agent asked to "add a `status` column to the orders table" often does the obvious thing: it looks at the current schema, sees no `status` column, and writes a new migration to add one. If a migration adding that exact column already ran, and only the migration file itself was deleted, renamed, or is sitting in a branch the agent has not checked out, the agent has no way to know that from the schema alone.
The result depends on the database. Some errors loudly: "column already exists," a failed migration, a clear signal something is wrong. Others fail silently in a worse way, a migration that adds a column with a default value succeeds a second time without complaint, but a migration that backfills data runs its backfill logic twice, which can double-count aggregates or duplicate the rows it was supposed to fix.
The three places this actually bites
**A migration got squashed or renamed** during a cleanup, and the agent's context window still contains the old filename from an earlier session, so it writes a migration that duplicates the squashed one's effect.
**The agent is working from a stale local database** that never received a migration the rest of the team already ran, so from its point of view the column genuinely does not exist yet, and it is technically correct that the local schema needs it, while being wrong that a new migration is the right way to add it.
**A migration exists in a git branch the agent has not seen**, most commonly when an agent is working across a rebase or a branch switch mid-session and its understanding of "what has run" is a snapshot from before the switch.
The fix: make migration history a checked fact, not an inference
Give the agent an explicit instruction to check applied state before writing new schema changes, and give it the command to check it with:
Before writing a new migration, run [prisma migrate status /
python manage.py showmigrations / rails db:migrate:status] and
confirm the change you are about to make has not already been
applied. If a migration with a similar name or effect already
exists in the migrations folder, tell me and ask before writing
a new one, do not assume it is stale.This works because it replaces an inference (the agent guessing from the current schema) with a lookup against the one source that actually tracks history. The migrations folder plus the migration-status table are ground truth. The schema alone is not, since a schema that already has the column looks identical whether it got there through the migration you expect or a different one entirely.
Distinct from the locking problem, and how they connect
This is a different failure from the one covered in AI coding agent database migrations, which focuses on lock behavior an agent cannot infer from your schema, specifically the danger of a migration that locks a large table for the duration of a blocking schema change. That post is about a migration behaving badly while it runs for the first time. This one is about a migration running a second time when it should not run at all. Both come from the same root cause: an agent that reasons from the schema it can see rather than the operational history it cannot, and both are fixed the same way, by giving the agent an explicit command to check state rather than infer it.
If your team is mid-way through changing database platforms entirely, the state-tracking problem gets sharper, since migration history often does not port over cleanly. Migrating an AI-built app from SQLite to Postgres covers what to do with your existing migration history during that specific move.
A pre-flight checklist worth pasting into your agent's instructions
Run the migration-status command before writing a new migration, every time, not just when something looks wrong.
Search the migrations folder by effect, not just by name, an agent renaming things over several sessions can produce two migrations that do the same thing under different filenames.
If working across a branch switch or rebase, re-run the status check after the switch completes, not before.
Treat "the column doesn't exist in my local schema" as a question to verify against migration history, not as sufficient evidence a new migration is needed.
Frequently asked questions
How do I know if a migration already ran without asking the AI agent?
Query your framework's migration-tracking table directly: `_prisma_migrations` for Prisma, `django_migrations` for Django, `schema_migrations` for Rails and many others. Every row in that table is a migration your database has already applied, regardless of what your current branch's migration folder contains.
Is it dangerous to run a migration twice?
It depends on what the migration does. Adding a column with `IF NOT EXISTS` or an equivalent guard is usually harmless the second time. A migration that backfills or transforms data is often not idempotent, and running it twice can double-apply the transformation, which is the more dangerous and more common case worth specifically guarding against.
Can I make migrations themselves safe to re-run instead of relying on the agent checking first?
Yes, and it is worth doing regardless of whether an AI agent is involved. Writing migrations idempotently (`ADD COLUMN IF NOT EXISTS`, checking for existing rows before a backfill) is good practice on its own. It does not replace checking migration history, since an idempotent migration that silently no-ops the second time can still mask a real problem, like the agent not realizing a change it thinks it is making has zero effect.
Does this problem get worse with multiple AI coding agents working on the same codebase?
Yes, meaningfully. Two agents working in parallel branches can each write a migration for the same schema change without either one seeing the other's work, and the collision only becomes visible at merge time. This is one of the concrete costs of parallel agentic work worth weighing against its speed benefit, especially on schema changes specifically, where the migrations folder itself becomes a merge conflict even when the underlying database change is compatible.
How did this land?
About the author

Developer Advocate
Steve builds something with Swarmz every week and writes up what worked, what broke, and what he'd do differently. Tutorials and hands-on guides are his lane.


