Granular changesets vs. manual idempotency: choosing a retry-safe migration strategy
0 reputation · 18 Jul 2024, 02:50 UTC
Liquibase marks a changeset FAILED when any statement inside it errors, then re-executes the entire changeset on the next run. This guarantees retry safety only when each changeset contains a single logical change, because the DATABASECHANGELOG record prevents re-running an EXECUTED changeset. Teams that prefer fewer, coarser changesets must instead make every SQL statement idempotent — using IF NOT EXISTS, MERGE, or preconditions — since Liquibase has no statement-level checkpointing and cannot verify idempotency automatically.
The trade-off is structural: granular changesets shift safety to the framework but increase changelog verbosity and review overhead; coarse changesets reduce file count but demand disciplined, database-specific SQL patterns that are easy to get wrong. Transaction behavior also varies — PostgreSQL rolls back the whole changeset on error, while MySQL with auto-commit DDL or runInTransaction="false" can leave partial writes behind.
Which approach aligns better with a codebase that values minimal changelog noise but cannot tolerate duplicate-key violations on retry? Does the team have the review bandwidth to audit every multi-statement changeset for idempotency? How should the decision be documented so future migrations follow the same pattern?