Skip to content
Latchkey

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 migrate job.
  • Make the deploy job needs: migrate so 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.sh

Common 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-minutes for the migrate job.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →