Files
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

69 lines
4.2 KiB
Markdown

# 7. Why there is no undo
[← 6. Baselining an existing database](06-baselining-an-existing-database.md) · [Index](../README.md) · Next: [8. Concurrent startup and locking →](08-concurrent-startup-and-locking.md)
`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`](../src/test/java/com/ankurm/dbmigrations/flyway/FlywayUndoTest.java) 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`](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`](../src/test/java/com/ankurm/dbmigrations/flyway/FlywayCommunityCommandSurfaceTest.java)
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`](output/07-flyway-proprietary-stub-commands.txt))
<svg viewBox="0 0 700 160" xmlns="http://www.w3.org/2000/svg" font-family="monospace" font-size="13">
<rect x="20" y="20" width="300" height="120" rx="6" fill="#eef2ff" stroke="#4f46e5"/>
<text x="170" y="42" text-anchor="middle">flyway-core (Community, Apache-2.0)</text>
<text x="40" y="65" font-size="12">migrate() ✓ real</text>
<text x="40" y="85" font-size="12">baseline() ✓ real</text>
<text x="40" y="105" font-size="12">clean() ✓ real</text>
<text x="40" y="125" font-size="12">undo() — compiles, throws at runtime</text>
<path d="M330 125 L400 125" stroke="#334155" stroke-width="2" marker-end="url(#a4)"/>
<rect x="400" y="95" width="270" height="60" rx="6" fill="#fee2e2" stroke="#dc2626"/>
<text x="535" y="120" text-anchor="middle">FlywayRedgateEditionRequiredException</text>
<text x="535" y="138" text-anchor="middle" font-size="11">only at the moment undo() is called</text>
<defs><marker id="a4" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#334155"/></marker></defs>
</svg>
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](https://www.red-gate.com/products/flyway/editions/) (`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](12-the-oss-license-service.md) verifies what actually happens on the Community jar's license-checking path, and it is not a stub-and-throw pattern at all.