Add db-migrations-expand-contract: zero-downtime schema migrations proven with a real 4-deploy rolling run

Companion code for Zero-Downtime Database Migrations: Expand-Contract in Practice
with Spring Boot: a full expand/migrate-writes/migrate-reads/contract sequence run
as an actual rolling deploy across two live replicas, with a load generator sending
continuous HTTP traffic through all four deploys (99.98% success, every residual
error traced to a root cause rather than left unexplained). Findings include a real
NOT NULL constraint trap in the expand migration, a backfill-window bug in the read
switch, H2's AUTO_SERVER=TRUE single-point-of-failure behavior under a rolling
restart, the drain-before-SIGTERM fix needed to close a health-check gap during
graceful shutdown, and H2 silently discarding a concurrently committed INSERT during
an ALTER TABLE ADD/DROP COLUMN rebuild - confirmed, by primary source, to be an
H2-specific behavior rather than a property of the technique itself.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019Fb7vW8vLyLKngBc4R3huA
This commit is contained in:
2026-09-16 19:22:48 +00:00
co-authored by Claude Sonnet 5
parent 22c30d4a5b
commit e478eafda3
60 changed files with 3561 additions and 0 deletions
+1
View File
@@ -22,6 +22,7 @@ files.
| [`spring-batch/`](spring-batch) | [Spring Batch on Boot 4.1: Jobs, Steps, Chunk Processing and Restartability](https://ankurm.com/) | a job that fails mid-chunk and resumes exactly where it left off across two separate JVMs, skip vs. restart on the same poisoned row, the resourceless job repository that forgets a restart ever happened, and the `chunk(int)` vs `chunk(int, tx)` builder split |
| [`spring-batch-partitioning/`](spring-batch-partitioning) | [Spring Batch Partitioning and Parallel Steps: Scaling a 10-Million-Row Job](https://ankurm.com/) | the real grid-size sweep at 10M and 300K rows (best speedup 1.42x, on 2 cores), `MultiResourcePartitioner` ignoring gridSize entirely, a rejected partition's `StepExecution` stuck at `STARTING` forever, and Spring Batch 6.0's new `JobOperator#recover` unsticking it |
| [`db-migrations-flyway-liquibase/`](db-migrations-flyway-liquibase) | [Flyway vs Liquibase for Spring Boot 4: Migrations, Rollbacks and Baselines](https://ankurm.com/flyway-vs-liquibase-spring-boot-4-migrations-rollbacks-baselines/) | Flyway Community's `undo` throwing `FlywayRedgateEditionRequiredException` at runtime, a real Liquibase 5.0.3 filename-caching defect that produces a phantom successful run, Liquibase's 10-second default lock-poll rate versus Flyway's near-instant row lock, the FSL license change and its ASF/Keycloak fallout, and what actually happens when both tools are enabled against one database |
| [`db-migrations-expand-contract/`](db-migrations-expand-contract) | [Zero-Downtime Database Migrations: Expand-Contract in Practice with Spring Boot](https://ankurm.com/zero-downtime-database-migrations-expand-contract-spring-boot/) | a real 4-deploy rolling sequence against two live replicas with a load generator proving 99.98% success, H2's `AUTO_SERVER` single-point-of-failure trap, a `NOT NULL` constraint that fails every Stage 4 insert, and `ALTER TABLE` silently dropping a concurrently committed row with no exception thrown |
Articles whose text is kept here rather than only on the blog have it under
`<directory>/post/``post.md` for the body and `meta.md` for the title, excerpt and