Let's say we have a Django project called Alpha. Developers work on Alpha on their dev environment before deploying the Django project to Heroku. The Procfile may look something like:
release: python manage.py migrate
web: python -m gunicorn wsgi:application
When a developer tries to deploy a new version of Alpha, the project is shipped altogether with its migrations files (as recommended). At the end of the deployment, Heroku will execute the release statement python manage.py migrate to make all the relevant changes to the database. Because release is part of the overall deployment process, if it fails then the new code will not be deployed.
However... While the code will be reverted back to what it was before the deployment (as expected), the potential changes to the Heroku's database are going to be permament. For example, let's assume that the new version has three new migrations:
001100120013
The first two migrations are executed correctly and the database is changed accordingly. They are also added to the database table django_migrations. The last one, however, contains an issue (e.g., it defines a constraint that the stage data don't respect).
In this scenario, the code on Heroku (both /migrations/ and models.py) and the database on Heroku are now vastly out of sync: in fact, the database reflects changes whose migrations are not even present in the code repository. This can generate all sorts of problems.
How to prevent to find oneself in this predicate and insure code and data are always 100% sync'ed on both stage and prod?
Post Scriptum
Heroku has the following snippet as part of its documentation:
Use transactions for database migrations
When performing a database migration, always use transactions. A transaction ensures that all migration operations are successful before committing changes to the database, minimizing the possibility of a failed partial migration during the release phase. If a database migration fails during the release phase (i.e., the migration command exits with a non-zero status), the new release will not be deployed. If transactions were not used, this could leave the database in a partially migrated state. We suggest using heroku run, rather than the release phase, to make schema/data corrections.