What “migration conflict” usually means
- Two branches add migrations that collide:
- same version (Flyway
V12__...) - same object change (both alter
userstable)
- same version (Flyway
- One branch merges and the other now fails in CI/prod
- People “fix” by editing old migrations (🚫)
Flyway (versioned files): conflict management
1) Make versions unambiguous
Rule: never “guess” next number manually.
Common patterns:
- Timestamp versions (best for big teams)
V20260115_1042__add_users_status.sql
- Or allocate ranges per team/service (less common)
This eliminates “two people created V12”.
2) CI must run migrations on a clean DB
Pipeline:
- start ephemeral Postgres (Testcontainers)
- run
flyway migrate - run smoke tests
- (optional) run
flyway validate
If two migrations conflict (e.g., both add same column), CI catches it early.
3) Use “expand–migrate–contract” for shared objects
Avoid breaking changes that depend on merge order:
- Expand: add new column/table nullable
- Migrate: backfill + dual write
- Contract: drop old column later
This prevents “branch A renamed column, branch B still writes old name” disasters.
4) Never edit an applied migration
Fix with a new migration:
V20260115_1205__fix_users_status_default.sql
Liquibase (changesets): conflict management
1) Enforce unique changeset IDs
Rule: ID must be globally unique in repo.
Good patterns:
2026-01-15-add-users-statusTEAM-1234-add-users-status
2) One changeset = one intent
Small, reviewable changesets reduce merge conflicts in XML/YAML.
3) Use contexts/labels only when needed
They help when you truly have environment-specific differences, but overuse creates confusion.
Cross-tool best practices (what actually works)
✅ A) Ownership and “migration PR discipline”
- Any migration PR must answer:
- Is it backward compatible with the previous app version?
- What’s the rollout plan (expand/contract)?
- What’s the risk on big tables (locks, runtime)?
✅ B) “Migration captain” mindset for hot tables
For heavily used tables:
- assign an owner/reviewer
- coordinate big changes
- avoid concurrent edits across teams
✅ C) Lock migrations to one per PR (most of the time)
It keeps reviews focused and reduces conflict surface area.
✅ D) Use ephemeral environments (or at least staging) that match prod
Conflicts often appear only with realistic data volume and constraints.
What not to do (interview red flags)
- “Just edit the older migration”
- “Delete the history table”
- “Turn off validation to unblock”
Interview-ready answer (concise)
We prevent migration conflicts with deterministic versioning (often timestamps), strict CI that applies migrations on a clean DB and validates checksums, and backward-compatible schema evolution using expand–migrate–contract. If conflicts still happen, we fix forward with a new migration rather than rewriting history.