agent ran prisma migrate dev against the shared staging database and wiped everyone's data
Recovery and prevention after an agent ran prisma migrate dev against a shared staging database and wiped data URIs restoring from backup, and the guardrails that keep migrate dev off shared databases. Use when migrate dev reset a database it should never have touched. Not for migrate deploy issues.
TL;DR
prisma migrate dev is a development command: when it detects drift it can reset the database, which is catastrophic on a shared staging instance. Restore the database from backup immediately, then make the mistake structurally impossible: agents only run migrate dev against personal databases, shared environments get migrate deploy exclusively, and a connection guard refuses dev commands against non-local databases.
The query
agent ran prisma migrate dev against the shared staging database and wiped everyone's dataUse this when
- prisma migrate dev wiped a shared staging database
- migrate dev reset a database with real data
- Need guardrails keeping migrate dev off shared databases
- An agent pointed migrate dev at the wrong database
Not for
- migrate deploy failures (a different command, different risks)
- Drift on a personal dev database (migrate dev is allowed to reset those)
- Data loss from application bugs (not a migrate dev problem)
Steps
1. Stop everything and assess
Halt the agent and any jobs writing to the staging database. Check what was lost: which tables were reset, whether the data is reconstructible from elsewhere.
Expected output: a written damage assessment before any recovery action. Do not run more prisma commands against the database until you know the state.
2. Restore from backup
Restore the staging database from the most recent backup, then replay any migrations that should be there:
npx prisma migrate deployExpected output: the database is back with data intact through the backup point. Document what was lost after the backup point: that gap is the real cost of the incident.
3. Ban migrate dev on shared databases structurally
Add a wrapper or shell guard: migrate dev refuses to run unless the database URL is local (YOUR_HOST or a personal-db pattern). Shared staging and production URLs only ever see migrate deploy.
# guard: abort migrate dev against non-local databasesExpected output: the exact command that caused the incident now exits with an error instead of wiping data.
4. Separate the workflows in the runbook
Personal database: migrate dev freely. Shared staging: migrate deploy only, run by CI. Production: migrate deploy only, with approvals. Write the matrix down where the agent can read it.
Expected output: the agent's procedure has no path from "I want to iterate" to "shared database reset".
5. Verify backups actually exist for every shared database
The incident is also a backup audit: confirm automated backups run and restore cleanly for staging, not just production. A staging database nobody backs up is a database nobody can recover.
Expected output: a tested restore for each shared environment, on record.
Tool compatibility
prisma 4.x and 5.x. migrate dev vs migrate deploy semantics are the same across both.
Variant phrasings
prisma migrate dev wiped staging database
Steps 1 and 2: stop, assess, restore from backup.
prisma migrate dev reset shared database prevent
Steps 3 and 4: connection guard plus a written dev/deploy matrix.
prisma migrate dev vs deploy staging
Step 4: dev is for personal databases; shared environments get deploy, always.
Why it happens
migrate dev is designed for inner-loop development: it diffs, warns about drift, and resets the database to match the schema when you tell it to. Pointed at a shared database, "reset to match my schema" means "delete everyone's data". The command did exactly what it is for; the target was wrong. The guard belongs on the target, not on the command.
Edge cases
- A restore followed by migrate deploy can re-apply migrations the backup already contains: check migrate status before deploying onto a restore.
- If staging data cannot be restored (no backup), say so plainly and rebuild from seeds plus documented fixtures: do not pretend the restore worked.
- The same guard should cover any destructive dev command (db push --force-reset, db seed): the class of mistake is "dev command vs shared database", not this one command.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_SSkU9lqnMaA0Bl2yqYBFpA