CI/CD
Migrations are safe to run automatically as part of a deploy pipeline. The state is stored in MongoDB, so re-running migrate up against an already-migrated database is a no-op — only pending migrations are applied.
WARNING
Always run migrations before deploying new application code. Rolling back application code without rolling back migrations can cause schema mismatches. Plan rollback steps when writing the down function of any destructive migration.
Environment Variables
Set MIGRATE_DB_CONNECTION_URI as a secret in your CI/CD environment. All examples below assume this variable is available.
GitHub Actions
Run migrations as a step in a deployment workflow:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm ci
- name: Run migrations
run: npx migrate up
env:
MIGRATE_DB_CONNECTION_URI: ${{ secrets.MIGRATE_DB_CONNECTION_URI }}
# Deploy application after migrations succeed
- name: Deploy application
run: ./scripts/deploy.shGitLab CI
# .gitlab-ci.yml
stages:
- migrate
- deploy
run-migrations:
stage: migrate
image: node:22-alpine
script:
- npm ci
- npx migrate up
only:
- main
deploy-app:
stage: deploy
script:
- ./scripts/deploy.sh
needs: [run-migrations]
only:
- mainDocker — Init Container (Kubernetes)
A common pattern in Kubernetes is to run migrations in an init container before the application container starts. The init container exits before the app pod receives traffic:
# kubernetes/deployment.yaml
spec:
initContainers:
- name: run-migrations
image: your-org/your-app:latest
command: ['npx', 'migrate', 'up']
env:
- name: MIGRATE_DB_CONNECTION_URI
valueFrom:
secretKeyRef:
name: app-secrets
key: db-connection-uri
containers:
- name: app
image: your-org/your-app:latest
# ...