checkId: check.db.migrations.pending plugin: stellaops.doctor.database severity: warn tags: [database, migrations, postgres, schema]
Pending Migrations
This Doctor check tells an operator whether the platform’s database schemas have been brought up to date. It reads the real Stella Ops migration ledger at runtime and reports the applied migrations across every provisioned schema — a fast way to confirm that startup migrations actually ran after a deploy, upgrade, or fresh bootstrap.
What It Checks
Reads the per-schema <schema>.schema_migrations ledger that the platform migration runner (StartupMigrationHost / MigrationRunner) writes — NOT EF Core’s __EFMigrationsHistory, which Stella Ops does not use. It reports:
- the number of schemas that have a
schema_migrationsledger and the total applied migrations across them; - the most recently applied migration (by
applied_at); - applied migrations whose category requires manual coordination (
release/data), surfaced as evidence; - applied migrations whose
checksumis blank and therefore cannot be integrity-verified — reported as a failure.
This is a runtime check run from the Doctor process, which holds only a connection string and not each module’s embedded migration SQL. It therefore reports the applied ledger and the conditions it can verify directly against the database; it does not compute a pending-vs-source diff. The authoritative pending/blocking decision (including blocking startup on pending release/data migrations) belongs to each service’s StartupMigrationHost.
Why It Matters
A missing ledger means a service was never started against this database (so startup migrations never ran) or the database was reset and never re-converged. A blank-checksum row means a migration was recorded without a verifiable hash — usually an out-of-band insert or a pre-checksum runner build — and the schema’s integrity can no longer be trusted.
Common Causes
- The owning services were never started against this database, so
StartupMigrationHostnever provisioned the ledger - The database was reset and no service has converged its schema yet
- A migration row was inserted out-of-band or recorded by a pre-checksum runner build
- The connection points at the wrong database or instance
How to Fix
Docker Compose
docker compose -f devops/compose/docker-compose.stella-ops.yml logs --tail 200 doctor-web
docker compose -f devops/compose/docker-compose.stella-ops.yml exec postgres psql -U stellaops -d stellaops -c "SELECT table_schema FROM information_schema.tables WHERE table_name = 'schema_migrations';"
docker compose -f devops/compose/docker-compose.stella-ops.yml exec postgres psql -U stellaops -d stellaops -c "SELECT migration_name, category, checksum, applied_at FROM <schema>.schema_migrations ORDER BY applied_at DESC LIMIT 10;"
Confirm the owning services call startup migrations on boot instead of relying on one-off SQL initialization scripts. For a blank-checksum row, re-run the owning service so StartupMigrationHost re-records the normalized checksum, or restore from a known-good PostgreSQL snapshot if the row is spurious.
Bare Metal / systemd
journalctl -u <service-name> -n 200
psql -h <db-host> -U <db-user> -d <db-name> -c "SELECT migration_name FROM <schema>.schema_migrations WHERE checksum IS NULL OR checksum = '';"
Kubernetes / Helm
kubectl logs deploy/<service-name> -n <namespace> --tail=200
kubectl exec -n <namespace> <postgres-pod> -- psql -U <db-user> -d <db-name> -c "SELECT count(*) FROM <schema>.schema_migrations;"
Verification
stella doctor --check check.db.migrations.pending
Related Checks
check.db.migrations.failed- flags applied migrations that cannot be integrity-verifiedcheck.db.schema.version- validates the resulting schema shape
