Files
spring-boot-demo/db-migrations-flyway-liquibase/docs/07-why-there-is-no-undo.md
T
asmhatreandClaude Sonnet 5 3908331431 Add db-migrations-flyway-liquibase: Flyway vs Liquibase migrations, rollbacks and baselines on Spring Boot 4.1
Companion code for the Flyway vs Liquibase article: checksum validation, out-of-order
and repeatable migrations, baselining an existing schema, Flyway Community's undo/diff/deploy
stubs, concurrent-startup locking for both tools, Liquibase changeset identity and rollback
(auto-generated vs explicit), a verified Liquibase 5.0.3 filename-caching defect, the new
OSS license service, the FSL license change, and running both tools against one database.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Q6XdRjtsp4862EM44T7i9a
2026-09-15 07:08:57 +00:00

4.2 KiB

7. Why there is no undo

← 6. Baselining an existing database · Index · Next: 8. Concurrent startup and locking →

Flyway (the Community, Apache-2.0-licensed flyway-core artifact this module depends on) has a public method called undo(). It compiles. Its Javadoc reads like every other command. Nothing in its signature suggests it won't work — and that's exactly the trap: FlywayUndoTest migrates a real database, then calls flyway.undo() on it, and the call throws at runtime:

flyway.undo() threw: org.flywaydb.core.internal.license.FlywayRedgateEditionRequiredException
message: Flyway Redgate Edition Required: undo is not supported by OSS Edition
Download Redgate Edition for free: https://rd.gt/3GGIXhh

(from docs/output/06-flyway-undo-teams-required.txt)

undo isn't a special case singled out for this article — it's one of a whole family of commands that ship as compiled, callable, do-nothing stubs in the Community jar. FlywayCommunityCommandSurfaceTest doesn't take that on faith either: it opens the actual flyway-core jar on the test classpath at runtime and lists every class under org.flywaydb.core.internal.proprietaryStubs, so this list is read off the artifact Maven Central serves, not copied from a marketing page:

- auth
- check
- deploy
- diff
- difftext
- generate
- licensingconfigurationextensionstub.class
- model
- offlinepermitconfigurationextensionstub.class
- pattokenconfigurationextensionstub.class
- prepare
- undo

(from docs/output/07-flyway-proprietary-stub-commands.txt)

flyway-core (Community, Apache-2.0) migrate() ✓ real baseline() ✓ real clean() ✓ real undo() — compiles, throws at runtime FlywayRedgateEditionRequiredException only at the moment undo() is called

The practical consequence: a compile-time check, a code review, or an IDE's autocomplete cannot tell you that undo() needs a Redgate Teams or Enterprise license. Only calling it — or reading the bytecode this test reads — does. For everyday rollback needs on the Community edition, the honest options are the ones Flyway's own OSS command set actually supports: write and ship a new, forward-only migration that reverses the change, or restore from a backup taken before the migration ran. Both are less elegant than flyway undo, and both actually work on the free jar.

Going deeper

  • Flyway editions comparison (rel="nofollow") — the vendor's own breakdown of which commands need which tier.
  • This is not a licensing violation to work around. The stub classes exist so a Community user who calls one of these APIs gets a clear runtime exception naming the required edition, rather than a NoSuchMethodError or a silent no-op — it's arguably the more honest of the two ways to gate a feature.
  • Liquibase's own commercial/community split works differently — chapter 12 verifies what actually happens on the Community jar's license-checking path, and it is not a stub-and-throw pattern at all.