.agents/skills/generate-migration/SKILL.md
Generate migrations automatically based on model changes:
sentry django makemigrations
For a specific app:
sentry django makemigrations <app_name>
Generate an empty migration (for data migrations or custom work):
sentry django makemigrations <app_name> --empty
__init__.pysentry django sqlmigrate <app_name> <migration_name> to verify the SQLsentry django migrate <app_name> — Sentry's migration framework runs its safety checks on apply, so this catches unsafe ops (missing is_post_deployment, unsafe column changes, etc.) before CI does.When editing a generated migration (e.g. swapping DeleteModel for SafeDeleteModel), leave the auto-generated is_post_deployment comment block in place. It documents a non-obvious flag with concrete guidance for future migration authors — useful context, not fluff. Only remove a comment if it's stale or contradicts the code.
db_default=<value> instead of default=<value> for columns with defaultsnull=Truedb_default setFor large tables, set is_post_deployment = True on the migration as index creation may exceed the 5s timeout.
null=True) if not alreadyRemoveField with SafeRemoveField(..., deletion_action=DeletionAction.MOVE_TO_PENDING)SafeRemoveField(..., deletion_action=DeletionAction.DELETE)Two-phase process — the historical_silo_assignments entry must be added in phase 1.
Phase 1 — Remove the model class (MOVE_TO_PENDING)
DeleteModel with SafeDeleteModel(..., deletion_action=DeletionAction.MOVE_TO_PENDING)historical_silo_assignments in src/sentry/db/router.py (or getsentry/db/router.py for getsentry models). Pick the silo the model used — usually SiloMode.CELL.Phase 2 — Drop the table (DELETE)
After phase 1 has deployed, create a second migration with SafeDeleteModel(..., deletion_action=DeletionAction.DELETE). Leave the historical entry in place — the table-drop migration relies on it to resolve the silo.
Don't rename in Postgres. Use db_column or Meta.db_table to keep the old name.
If migrations_lockfile.txt conflicts:
bin/update-migration <migration_name>
This renames your migration, updates dependencies, and fixes the lockfile.