checkId: check.postgres.migrations plugin: stellaops.doctor.postgres severity: warn tags: [database, postgres, migrations, schema]

PostgreSQL Migration Status

This Doctor check confirms that a service’s database schema is fully migrated and matches what the running code expects. In Stella Ops, missing migrations are the number-one cause of post-upgrade service failures — a service can start and look healthy, then return 500s on the first request that touches a table or column the migration never created. This check is aimed at operators validating a deploy, an upgrade, or a fresh bootstrap.

What It Checks

Connects to PostgreSQL and examines the EF Core migration history to identify pending migrations:

  1. Migration table existence: checks for the __EFMigrationsHistory table in the public schema. Warns if the table does not exist.
  2. Applied migrations: queries the migration history table (ordered by MigrationId descending) to determine which migrations have been applied.
  3. Pending migrations: compares applied migrations against the expected set to identify any unapplied migrations. Warns if pending migrations are found.

Evidence collected: TableExists, AppliedCount, PendingCount, LatestApplied, PendingMigrations, Status.

The check requires ConnectionStrings:StellaOps or Database:ConnectionString to be configured.

Why It Matters

Pending database migrations mean the schema does not match what the application code expects. Any request that touches a missing table or column — or relies on a schema feature that was never applied — fails with a 500 error. Because the failure surfaces on first use rather than at startup, it can stay hidden until a user or background job hits the affected path, which makes proactive detection valuable.

Common Causes

How to Fix

Docker Compose

# Check migration status
docker compose -f docker-compose.stella-ops.yml exec platform \
  stella db migrations status

# Apply pending migrations
docker compose -f docker-compose.stella-ops.yml exec platform \
  stella db migrate

# If auto-migration is configured, restart the service (it migrates on startup)
docker compose -f docker-compose.stella-ops.yml restart platform

# Verify migration status after applying
docker compose -f docker-compose.stella-ops.yml exec platform \
  stella db migrations list

Ensure auto-migration is enabled:

services:
  platform:
    environment:
      Platform__AutoMigrate: "true"

Bare Metal / systemd

# List pending migrations
stella db migrations list --pending

# Apply pending migrations
stella db migrate

# Verify all migrations are applied
stella db migrations status

# If auto-migration is configured, restart the service
sudo systemctl restart stellaops-platform

Edit /etc/stellaops/platform/appsettings.json to enable auto-migration:

{
  "Platform": {
    "AutoMigrate": true
  }
}

Kubernetes / Helm

# Check migration status
kubectl exec -it <platform-pod> -- stella db migrations status

# Apply pending migrations
kubectl exec -it <platform-pod> -- stella db migrate

# Or use a migration Job
kubectl apply -f - <<EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: stellaops-migrate
spec:
  template:
    spec:
      containers:
      - name: migrate
        image: stellaops/platform:latest
        command: ["stella", "db", "migrate"]
      restartPolicy: Never
EOF

Set in Helm values.yaml:

platform:
  autoMigrate: true
  migrations:
    runOnStartup: true

Verification

stella doctor run --check check.postgres.migrations