How to Run Database Migrations on Deploy With GitHub Actions
Apply migrations in a dedicated job that must succeed before the app deploy job runs, so code never ships ahead of its schema.
Put migrations in their own job that needs nothing but is needed by deploy. Inject the database URL from a secret and run your migration tool (Prisma, Flyway, Alembic, or similar). Deploy only after it succeeds.
Steps
- Store the database URL as a secret (or scope it to the environment).
- Run migrations in a
migratejob. - Make the
deployjobneeds: migrateso it only runs after a clean migration.
Workflow
.github/workflows/deploy.yml
jobs:
migrate:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
deploy:
needs: migrate
runs-on: ubuntu-latest
environment: production
steps:
- run: ./scripts/deploy.shCommon pitfalls
- Running migrations after the deploy means new code can hit an old schema and error; migrate first.
- A backward-incompatible migration breaks the still-running old version during rollout; use expand-then-contract migrations.
- A long-running migration can exceed the job timeout; raise
timeout-minutesfor the migrate job.
Related guides
How to Gate a Production Deploy With Approvals in GitHub ActionsRequire a human approval before a production deploy in GitHub Actions by targeting a protected environment wi…
How to Do a Blue-Green Deploy With GitHub ActionsRun a blue-green deployment from GitHub Actions by deploying the new color, smoke testing it, then switching…