Skip to main content

Running Database Migrations

This guide explains how to configure your application to run a pre-deployment database migration job before the main service starts.

Infrastream runs migrations as a lifecycle job. You attach a BEFORE job to your application and describe it with a JobConfig manifest. The platform provisions a one-off Cloud Run Job that runs your migration container, and the main service deployment is gated — it only proceeds after the BEFORE job completes successfully.

Note: The older runMigrationJob flag has been removed. Use the jobs + JobConfig model below.


Prerequisites

  • You must have an existing Application manifest.
  • Your application's BuildDefinition or ExternalApplication should produce a container image that can run migrations (e.g., a Flyway, Liquibase, or custom migration runner).
  • You must have a Database manifest provisioned.

Step 1: Declare a BEFORE job on your Application

Reference the migration job in your Application's spec.jobs, and grant it database access:

apiVersion: lowops.manifests.v1
kind: Application
metadata:
name: payment-api
application-set: payments
release-track: main-track
organizational-unit: retail-banking
organization: fincorp
spec:
source: payment-api
container: payment-api
target: CLOUD_RUN
project: payment-gateway
jobs:
- name: migrate
type: BEFORE # Runs before each deployment (also: AFTER, SCHEDULED, ON_DEMAND)
accessControl:
database:
name: payments-db
schema: payments # A logical database declared in the Database's spec.databases
privileges:
- USAGE
- CREATE
secretSource:
envVar: DATABASE_URL

Step 2: Describe the job with a JobConfig manifest

For each environment, create a JobConfig whose metadata.name follows the <application-name>-<job-name> pattern (here, payment-api-migrate). It reuses the application's container image and defines the command that runs the migration:

apiVersion: lowops.manifests.v1
kind: JobConfig
metadata:
name: payment-api-migrate # <application-name>-<job-name>
project: payment-gateway
environment: production
organizational-unit: retail-banking
organization: fincorp
spec:
version: "1.4.0" # Image tag to run for the migration
container:
command: ["/migrate.sh"] # Entrypoint that applies your migrations
env:
- name: MIGRATION_MODE
value: "up"

Step 3: Ensure Your Container Supports Migrations

The job reuses the application's container image. Ensure your Dockerfile or build pipeline produces an image that can run migrations when invoked.

Common patterns:

  • Flyway / Liquibase: override the entrypoint/command to apply migrations
  • Custom scripts: include a /migrate.sh script that the job invokes

If your migration tool manages schema objects itself, still declare the logical database in the Database manifest's spec.databases list (and enable any required PostgreSQL extensions there); the application's accessControl.database only grants privileges — it does not create tables.

Note: The platform creates a Cloud Run Job for the BEFORE step, and the main Cloud Run service is configured to depend on its successful completion.

Step 4: Commit, Review, and Merge

After your PR is merged, the deployment flow becomes:

The migration job runs before every deployment, ensuring your database schema is always up-to-date with the deployed code version.