This document explains how database migrations are handled automatically in the OpenShift deployment.
Prisma migrations are automatically run when the application is deployed to OpenShift using an init container. Migrations run before the main application container starts, ensuring:
- Migrations complete before the app accepts traffic
- If migrations fail, the pod won't start (fail-fast)
- Migrations run only once per pod
- Clear separation of concerns
The deployment includes an init container that:
- Uses the same image as the main application
- Runs
npx prisma migrate deploybefore the app starts - Uses the
DATABASE_URLfrom a Kubernetes Secret
The init container is configured in deployments/openshift/kustomize/base/backend-services/deployment.yml:
initContainers:
- name: migrate-db
image: artifacts.developer.gov.bc.ca/kfd3-fd34fb-local/backend-services:latest
command: ['npx', 'prisma', 'migrate', 'deploy']
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: postgres-cluster-pguser-admin
key: uri-
Database Secret: The
DATABASE_URLmust be available as a Kubernetes Secret. For CrunchyDB PostgresCluster, the secret is typically named:- Pattern:
{cluster-name}-pguser-{username} - Example:
postgres-cluster-pguser-admin - Key:
uri(contains the full PostgreSQL connection string)
- Pattern:
-
Dockerfile: The Dockerfile must include:
- Prisma CLI (included via
npm install) - Prisma schema and migrations directory
- Prisma CLI (included via
To check if the secret exists and view its structure:
oc get secret postgres-cluster-pguser-admin -o yamlIf the secret name is different, update the secretKeyRef.name in the deployment.
# Create a new migration
npm run db:migrate
# Check migration status
npm run db:status
# Reset database (WARNING: deletes all data)
npm run db:resetThe prisma migrate deploy command is used in production, which:
- Only applies pending migrations (safe for production)
- Does not create new migrations
- Is idempotent (safe to run multiple times)
-
Check the init container logs:
oc logs <pod-name> -c migrate-db
-
Verify the DATABASE_URL secret exists:
oc get secret postgres-cluster-pguser-admin
-
Test the connection string manually:
oc exec <pod-name> -c migrate-db -- env | grep DATABASE_URL
If your PostgresCluster creates secrets with a different naming pattern, update the deployment:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: <your-secret-name>
key: uri # or 'password', 'host', etc. depending on your secret structureEnsure:
- The database service is accessible from the pod
- Network policies allow connection
- The database user has proper permissions
- The database exists (created by PostgresCluster)
- Always test migrations locally before deploying
- Use init containers in production for better reliability
- Monitor migration logs during deployments
- Keep migrations small and focused - large migrations can cause downtime
- Use transactions when possible (Prisma does this by default)
- Backup before major migrations in production
deployments/openshift/kustomize/base/backend-services/deployment.yml- Init container configurationapps/backend-services/Dockerfile- Includes Prisma CLI and migrationsapps/shared/prisma/schema.prisma- Database schema (shared between backend-services and temporal)apps/shared/prisma/migrations/- Migration files (shared between backend-services and temporal)