A schema rollout test matrix runs the old and new application write shapes against each migration phase.
Spring schema rollout tests: check old and new writers at every phase
The local assertions
The source kit checks two points. After nullable expansion, an old insert omitting tenant_id succeeds and the backfill assigns both rows. After NOT NULL contraction, that old insert fails and a new insert with tenant_id succeeds. The tests inspect counts and stored values, not only exception types.
That is a useful local contract, but a production sequence has more states: old code on old schema, old code on expanded schema, new code on expanded schema, new code after backfill and new code on contracted schema. The first fixture and the second cover only a small subset in H2.
Move to the target engine
Run the exact versioned SQL against the production database engine in a disposable integration environment. Include realistic indexes and row counts, concurrent traffic, migration restart after failure, read replicas if used and DDL lock monitoring. Check that rollback to the previous application version is possible at each deployment stage; after contraction it may not be.
Do not infer Flyway history behavior from the direct JdbcTemplate tests; a separate FlywayReceiptMigrationTest now checks it on H2. The runner plan is separate. Keep a reviewer-visible record of which versions can coexist.
Checked source
mvn -q -Dtest=SchemaEvolutionContractTest testVerification boundary
SchemaEvolutionContractTest has two local H2 tests. The excerpt is shortened or a labelled design sketch; the kit contains the checked tests.
Costs and limits
A separate test-scoped Flyway fixture checks ordered files on H2. No target database, mixed-version process pair, realistic table volume or crash/restart flow is checked.
Common Mistakes
- Do not test only the final schema.
- Do not claim old-version rollback works after a breaking constraint.
- Do not use a tiny H2 table to estimate production DDL locks.
Read next
Spring database rollout: add a nullable column before changing every writer, Spring database backfill: assign historical rows before enforcing ownership, Spring database contract phase: reject old writers only after backfill, Spring Boot migrations: what a versioned runner must add to the SQL test.
Checked file and migration continuation
Continue with Flyway expand and contract: show exactly when an old writer breaks.
Continue with checked Boot startup
Continue with Spring Boot migration target: test an old writer before closing the schema.
