Skip to content
Latchkey

How to Run Database Migrations Before Deploy in GitHub Actions

Shipping code that expects a new schema before the migration ran is a recipe for downtime; migrate first, then deploy.

Run migrations in a dedicated job that the deploy needs:, so a failed migration blocks the deploy entirely.

Steps

  • Put migrations in their own job with the database connection as a secret.
  • Make the deploy job needs: the migrate job.
  • Use forward-compatible (expand/contract) migrations so old and new code coexist.
  • Fail loudly so a broken migration stops the deploy.

Workflow

.github/workflows/deploy.yml
jobs:
  migrate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: ./migrate.sh up
  deploy:
    needs: migrate
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

Gotchas

  • Use expand/contract migrations so the currently running code does not break mid-deploy.
  • Make migrations idempotent so a retried job does not double-apply.
  • Latchkey runs migration jobs on cheaper runners that retry transient connection failures before the deploy.

Related guides

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