fix(prisma-cloud): deploy services only after their database migration - #334
Conversation
A service that uses a postgres() database could go live before the database's migration finished. The lowering published the warm-up's url to consumers, and nothing a consumer references pointed at the migration, so Alchemy ran the migration and the service deployment in parallel. The url output now also references the whole migration resource. Each consumer's environment row and deployment triggers carry that url, so the deployment waits until the schema is at the target, and a failed migration stops the new code from shipping. When the migration is a no-op, the url resolves from state at plan time and adds no wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kristof Siket <siket@prisma.io>
Amend ADR-0022 with the ordering rule its "no runtime schema check" guarantee depends on, and note why the window where old code runs against the new schema is safe. Update the core-model sketch of the postgres lowering, and tell users in the guide and the skill what the order means for them: a failed migration blocks the new code, and a new migration target redeploys the services that use the database. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kristof Siket <siket@prisma.io>
|
✅ Gizmo reviewed 868ff7a — posted 0 inline comment(s) this pass. Open findings: none Change walkthroughThis PR makes a service that consumes a Lowering — orm-postgres.ts now captures the previously discarded migration result and folds it into Tests — the new orm-postgres-ordering.test.ts drives the real descriptor and Output machinery: it asserts the url's upstream set includes both warm-up and migration, that the url still resolves to the connection string rather than migration attributes, and that a consumer-side environment row built from the url keeps the migration as an upstream. Docs & ADRs — the ADR-0022 amendment and the ADR index record the new ordering guarantee; |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Essentials Run ID: 📒 Files selected for processing (2)
Included review availability: This review used your included allowance. 2 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour. Summary by CodeRabbit
WalkthroughThe PostgreSQL lowering retains the migration result and publishes its URL through an output that depends on both database warm-up and migration completion. Tests verify these dependencies, including for a Prisma environment-variable row. The design documentation, guide, and skill text describe deployment ordering, migration failure blocking new code, and compatibility between the migrated schema and code that remains active during deployment. Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to The change describes migration-gated deployment without promising an unsupported redeployment behavior. It is mergeable after normal checks. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
commit: |
The guide and the skill promised that moving the migration target redeploys the consuming services. That happens today only because a trigger member left unresolved at plan time replaces the deployment conservatively; this change does not guarantee it. Keep the docs to what the ordering edge enforces: services deploy after the migration, and a failed migration stops the new code from shipping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kristof Siket <siket@prisma.io>
Test report: deploy order on a real platformResult: pass. With this PR, the service's deployment is created only after its database migration has finished. What was tested
Setup
Result: a fresh deployAll times are UTC on 2026-10-02. The 0.25.0 run used the same kind of module, earlier the same day.
During setup, two earlier attempts failed in the migration step, for a local install reason (see the setup note). In both, the service's deployment and the database URL row were not created. A failed migration blocked the new code, as the PR intends. Result: a redeploy with no changes
Setup note: not caused by this PRInstalling the three preview packages next to
With the plain install, npm nested a second copy of Not covered
Cleanup
🤖 Generated with Claude Code |
What happens today
A service that uses a
postgres()database can go live before that database's migration has finished. The deployment and the migration both depend only on the warm-up step, so they run in parallel.Seen in a rehearsal on the preview platform on 2026-10-02 with
@prisma/composer0.25.0: the service's deployment was live at 11:03:58, and the migration finished at 11:07:33. For three and a half minutes, the new code ran against a database that was not yet at its target.Why this is a bug
ADR-0022 says the deploy guarantees the live database is at the contract's hash, so the runtime binding does no schema check. The building-an-app guide has said "The deploy applies
migrations/before the service starts" since July. Nothing in the graph enforced that order. Before the warm-up step was added (d9f0db2), consumers got the plain connection url, so the edge to the migration never existed.The cause and the fix
orm-postgres.tscreated the migration and dropped its result, and publishedurl: warm.urlto consumers. Nowurlalso references the whole migration resource and still resolves to the same connection string:This follows the pattern in
deployment-edge.ts. The edge rides the environment row's value and the deployment's triggers, neverartifactPath(ADR-0048).rawPostgreshas no migration and is unchanged.What changes for users
The ADR-0022 amendment, the guide, and the
prisma-composer-core-conceptsskill say so.A side effect, not documented as a guarantee: when a deploy changes the migration (a new contract or ref), the url is still unresolved at plan time, so upstream replaces the consuming deployments conservatively, even when their code is unchanged.
core-model.mdshows the newurl.ADR-0048 still calls the ordering helper
dependsOnEnvironment. That was its name when the ADR was written; the code now calls itappAfterEnvironment. ADRs are append-only, so this PR leaves it.Tests
orm-postgres-ordering.test.tsdrives the real descriptor and Output machinery. Onmain: 1 pass, 2 fail. With the fix: 3 pass.@internal/prisma-cloud: 389 pass, 0 fail, 29 files (386 across 28 onmain).@internal/lowering: 198 pass.tsc --noEmitclean for both packages;biome checkclean on the changed files;lint:castsdelta 0.Not tested: the Postgres integration tests (no database was available) and an end-to-end deploy on the platform. A rehearsal should confirm the migration finishes before the deployment goes live.
🤖 Generated with Claude Code