Prev Next

Database / Redgate Flyway Interview questions

Last updated

1. What is Flyway? 2. What is a Flyway migration? 3. What are the types of Flyway migrations? 4. How do you name a Flyway versioned migration? 5. What is the flyway_schema_history table? 6. What are the core Flyway commands? 7. What does the flyway migrate command do? 8. What is the purpose of the flyway info command? 9. What is the purpose of flyway validate? 10. What is the purpose of flyway baseline? 11. How do you configure Flyway? 12. What are Flyway placeholders? 13. What are repeatable migrations used for? 14. What are Flyway callbacks? 15. What is the purpose of flyway clean? 16. What are the editions of Flyway? 17. How do you use Flyway with Spring Boot? 18. How do you use the Flyway Java API? 19. What is the difference between versioned and repeatable migrations? 20. How does Flyway order migrations? 21. How does Flyway detect modified migrations? 22. What is the purpose of flyway repair? 23. When should you use baselineOnMigrate? 24. What happens when a Flyway migration fails? 25. Why should applied migrations never be edited? 26. How does Flyway handle transactions? 27. When should you enable outOfOrder in Flyway? 28. How do you write a Flyway Java-based migration? 29. What is the difference between Flyway and Liquibase? 30. How do you manage Flyway configuration across environments? 31. How do you use Flyway with Docker? 32. How does Flyway prevent concurrent migrations? 33. Why is flyway clean disabled by default? 34. How do you roll back a Flyway migration? 35. How do you integrate Flyway into a CI/CD pipeline? 36. How do you migrate to a specific version using target? 37. Explain the execution flow of flyway migrate? 38. How do you achieve zero-downtime migrations with Flyway? 39. How do you introduce Flyway to an existing production database? 40. How do you troubleshoot a Flyway validate failed error? 41. How do you handle large data migrations in Flyway? 42. How can you use Flyway in a multi-tenant architecture? 43. How do you avoid version conflicts in team development? 44. What is a custom MigrationResolver and when would you use it? 45. How do you secure database credentials in Flyway? 46. How do you test Flyway migrations? 47. How do you use ignoreMigrationPatterns safely? 48. What does Flyway Desktop add to the command-line workflow? 49. Which is better and why: SQL or Java migrations in Flyway? 50. Explain the lifecycle of a Flyway migration from commit to production?

1. What is Flyway?

Flyway is a database migration tool that applies versioned changes to a database schema in a controlled, repeatable way. You keep each change as a small script (usually SQL), commit it to source control, and Flyway applies the scripts in order.

It records everything it has applied in a schema history table, so every environment (dev, test, production) can be brought to the same version by running one command. Flyway is now maintained by Redgate and ships as a command-line tool, Docker image, Maven and Gradle plugin, and Java API.

The idea is simple: treat the database like code, with version control and automated deployment.

Take quiz
What does Flyway use to know which scripts have already run?
A text file kept on the developer's laptop
The timestamp of the last Git commit
A cache inside the application server
A schema history table stored in the database
Flyway is mainly used to:
compress database backups
apply ordered, versioned schema changes to a database
tune slow SQL queries automatically

2. What is a Flyway migration?

A migration is a single script that changes the database, such as creating a table, adding a column, or loading reference data. Flyway treats each migration as one unit of work with a unique version (or a name, for repeatable ones).

Most migrations are plain SQL files, but Flyway also supports Java-based migrations when logic is too complex for SQL. Once a migration is applied, Flyway stores its version, description, checksum, and result in the history table.

A tiny example:

-- V1__create_customer.sql
CREATE TABLE customer (
  id   INT PRIMARY KEY,
  name VARCHAR(100) NOT NULL
);

Take quiz
In Flyway, a migration is best described as:
a full copy of the production database
a runtime thread pool setting
one script that moves the schema from one state to the next
Which details does Flyway record after applying a migration?
only the author's email address
the CPU usage of the server
version, description, checksum and success status
the full text of every SQL result set

3. What are the types of Flyway migrations?

Flyway supports three main kinds of migrations, each with a different filename prefix:

Type Prefix Behaviour
Versioned V Runs exactly once, in version order.
Repeatable R Re-runs whenever its checksum changes.
Undo U Reverses a versioned migration (paid editions).

Newer editions also offer baseline migrations (prefix B) that collapse many old versions into one script for fresh databases. Callbacks are scripts too, but they hook into lifecycle events rather than being migrations.

Pick by the object you are changing: versioned for things that change state once (tables, columns, data), repeatable for definitions you want kept current in a single file.

Take quiz
Which migration type re-runs when its file content changes?
Versioned migration
Repeatable migration
Baseline marker
Undo migration
Which prefix identifies a repeatable migration?
V
R
X
M

4. How do you name a Flyway versioned migration?

Use the pattern V<version>__<description>.sql. It starts with the prefix V, then the version, then a double underscore, then a description with words separated by single underscores.

Versions can have several parts separated by dots or underscores, such as 1.2.3. Flyway compares them numerically part by part, so 1.10 is newer than 1.2.

V1__create_customer.sql
V1_1__add_email_column.sql
V2.0__create_orders.sql

The prefix, separator, and suffix can be changed through sqlMigrationPrefix, sqlMigrationSeparator, and sqlMigrationSuffixes, but the defaults are what most teams use.

Take quiz
Which filename is a valid default versioned migration?
V3_add_index.sql
3__add_index.sql
V3__add_index.sql
migration-v3-add-index.sql
What separates the version from the description?
Two underscores
A single hyphen
A colon

5. What is the flyway_schema_history table?

It is the table Flyway creates in your database to track every migration it has run. Flyway reads it before each migrate to decide what is pending, and updates it after each script.

Older releases called it schema_version. The name and schema can be changed with the table and defaultSchema settings. Key columns:

Column Meaning
installed_rank Order in which scripts were applied
version / description Parsed from the filename
type / script SQL, JDBC, or baseline and the file name
checksum CRC32 of the script content
installed_by / installed_on Who ran it and when
execution_time / success Duration and outcome

Take quiz
Which column lets Flyway detect that a script was edited after it ran?
checksum
installed_on
execution_time
What was the schema history table called in much older Flyway versions?
flyway_log
db_changes
schema_version
migration_master

6. What are the core Flyway commands?

Flyway commands are run from the CLI, Maven, Gradle, or the API. The ones you will use daily are:

Command Purpose
migrate Applies pending migrations
info Shows applied, pending, and failed migrations
validate Checks applied migrations against local files
baseline Marks an existing database at a starting version
repair Fixes the history table (failed rows, checksums)
clean Drops all objects in the configured schemas

Paid editions add undo, check, and other commands for reports, drift detection, and dry runs.

Take quiz
Which command applies pending migrations?
info
validate
baseline
migrate
Which command only reports the state of migrations without changing the database?
info
repair
clean
migrate

7. What does the flyway migrate command do?

flyway migrate scans the configured locations, compares what it finds with the schema history table, and runs every pending migration in version order. Repeatable migrations whose checksum changed run last.

Before applying anything it validates previously applied scripts (validateOnMigrate is on by default) and creates the history table if it does not exist. If the database is non-empty and has no history table, migrate stops and asks you to baseline first.

flyway -url=jdbc:postgresql://localhost:5432/shop -user=app -password=secret -locations=filesystem:sql migrate

The command prints how many migrations were applied and the schema version it ended on, and it exits with code 0 only on success, so pipelines can rely on the exit status.

Take quiz
In what order does migrate apply pending versioned scripts?
Ascending version number
Alphabetical by description
Newest file modification time first
Random order
What happens by default if an applied script was changed before migrate runs?
Validation fails and migrate stops
Flyway silently re-runs it
Flyway deletes the history row

8. What is the purpose of the flyway info command?

flyway info prints a status table of every migration Flyway can see, both on disk and in the history table. It never changes the database schema, so it is safe to run at any time, including in production checks.

Typical states include Pending, Success, Failed, Missing, Out of Order, Ignored, and Future. Teams run it before a release to confirm what will be applied.

+-----------+---------+---------------------+------+---------+
| Category  | Version | Description         | Type | State   |
+-----------+---------+---------------------+------+---------+
| Versioned | 1       | create customer     | SQL  | Success |
| Versioned | 2       | add email column    | SQL  | Pending |
+-----------+---------+---------------------+------+---------+

Take quiz
Which state means a script exists on disk but has not been applied yet?
Pending
Missing
Future
Does flyway info modify the schema of your application tables?
Yes, it applies pending scripts
Yes, it drops unused tables
No, it only reads and reports
Yes, it rewrites checksums

9. What is the purpose of flyway validate?

flyway validate checks that the migrations already applied to the database still match the scripts you have locally. It compares versions, descriptions, and checksums, and fails if anything differs.

It catches problems early, for example someone editing an old script, deleting one, or merging a branch that introduced a lower version. Run it in pull-request builds so bad changes never reach a shared environment.

It only reads the database, so it is cheap and safe to run on every build, long before anything is deployed.

Take quiz
What does validate compare to find edited scripts?
File sizes versus disk quota
Author names versus Git users
Table row counts versus file line counts
Stored checksums versus current file checksums
Where is validate most useful in a team workflow?
Only after dropping the database
Inside application business logic
On the developer's printer
In CI builds before merging or deploying

10. What is the purpose of flyway baseline?

baseline tells Flyway that an existing database is already at a certain version, so older migrations should not run. It creates the history table and inserts a single baseline row.

You use it when adopting Flyway on a database that was built by hand or by another tool. Set the version with baselineVersion, and every migration at or below that version is skipped. Only higher versions run on the next migrate.

flyway -baselineVersion=5 -baselineDescription=&quot;Existing prod schema&quot; baseline

Baselining is a one-time step per database. Afterwards the history table shows a baseline row, and Flyway behaves as it would on a database it built itself.

Take quiz
After baselining at version 5, which migrations will migrate run?
All versions from 1
Only version 5
Nothing, ever
Only versions above 5
Baseline is typically used when:
creating a brand-new empty database
exporting data to CSV
adopting Flyway on an already populated database

11. How do you configure Flyway?

Flyway reads settings from several places, and later sources override earlier ones: config files, then environment variables, then command-line arguments. In Flyway 10 and later, a flyway.toml file with named environments is the recommended style, and the classic flyway.conf still works.

# flyway.conf
flyway.url=jdbc:postgresql://localhost:5432/shop
flyway.user=app
flyway.locations=filesystem:sql
flyway.baselineOnMigrate=false

Environment variables use the form FLYWAY_URL, FLYWAY_USER, and so on. This is handy for CI, where secrets should not be stored in files.

If a value seems to be ignored, run with -X. The debug output prints the resolved configuration, so you can see which source won.

Take quiz
Which source has the highest priority when the same setting appears twice?
The default config file
Command-line arguments
A comment in a SQL file
How is the url setting written as an environment variable?
flyway-url
FLYWAY_URL
URL_FLYWAY
FLYWAY.DB

12. What are Flyway placeholders?

Placeholders are named variables written as ${name} inside SQL migrations. Flyway replaces them with configured values before running the script, which lets one file work across environments.

Define them with flyway.placeholders.name=value or -placeholders.name=value. Flyway also provides built-ins such as ${flyway:defaultSchema}, ${flyway:user}, and ${flyway:timestamp}.

CREATE TABLE ${schema_name}.audit_log (
  id INT PRIMARY KEY,
  note VARCHAR(200)
);

If a placeholder is used but never defined, the migration fails rather than running with a literal ${...}.

Placeholders also work in callbacks. If ${ } clashes with your SQL, change the delimiters with placeholderPrefix and placeholderSuffix.

Take quiz
How is a placeholder referenced in a SQL migration?
${name}
#{name}
%name%
{{name}}
What happens when a referenced placeholder has no value?
Flyway uses an empty string silently
Flyway picks a random value
The migration fails with an error
The line is skipped without notice

13. What are repeatable migrations used for?

Repeatable migrations manage objects that are better redefined than altered, such as views, stored procedures, functions, and triggers. They are named R__description.sql and have no version.

Flyway re-applies one whenever its checksum changes, and always after all pending versioned migrations. They run in alphabetical order of description, so write them with CREATE OR REPLACE so they can safely run again.

-- R__customer_summary_view.sql
CREATE OR REPLACE VIEW customer_summary AS
SELECT id, name FROM customer;

Because repeatables run in alphabetical order, name them so dependencies come first, for example R__01_base_view.sql before R__02_report_view.sql.

Take quiz
Which database objects are the best fit for repeatable migrations?
Primary key values
Views and stored procedures
Application log files
Backup schedules
When does Flyway re-run a repeatable migration?
On every single migrate regardless of content
Only on the first day of the month
When its checksum changes

14. What are Flyway callbacks?

Callbacks are scripts or Java classes that Flyway runs automatically at specific points in its lifecycle. They are useful for housekeeping around a deployment, such as refreshing permissions or logging.

SQL callbacks are placed in the same location as migrations and named after the event, for example beforeMigrate.sql or afterMigrate.sql. Common events:

Event Runs
beforeMigrate / afterMigrate Once around the whole migrate run
beforeEachMigrate / afterEachMigrate Around every single migration
beforeValidate, beforeClean Around validate and clean commands

A callback can also be a Java class implementing the Callback interface, which suits things like sending a notification after a deployment.

Take quiz
Which file name runs once after a migrate run finishes?
afterMigrate.sql
afterEach.sql
V0__after.sql
Callbacks are useful for:
replacing the schema history table
choosing the JDBC driver
hooking tasks into Flyway lifecycle events
encrypting migration files

15. What is the purpose of flyway clean?

flyway clean drops every object in the configured schemas: tables, views, procedures, and the history table itself. It gives you a blank slate, which is handy before re-running all migrations in a throwaway dev or test database.

It is destructive and must never be pointed at production. Recent Flyway versions disable it by default; you must explicitly set cleanDisabled=false to use it.

flyway -cleanDisabled=false clean migrate

A common local workflow is clean followed by migrate. It rebuilds the database from scratch and proves your scripts alone can recreate the schema.

Take quiz
What does clean remove?
Only rows older than 30 days
All objects in the configured schemas
Only the history table
Only the latest migration
Where is clean considered acceptable to run?
Production during business hours
Any shared database to save space
Read replicas used by analysts
Disposable dev or test databases

16. What are the editions of Flyway?

Flyway comes in a free Community edition and paid Teams and Enterprise editions from Redgate. Community is open source and covers the core flow: versioned and repeatable migrations, callbacks, placeholders, and the main commands.

The paid editions add features aimed at larger teams, such as undo migrations, dry runs, change and drift reports, additional database support, and vendor support. Exact feature lists and database coverage change between releases, so check the current Redgate documentation before choosing.

Community is enough for many projects, so start there and move up only when you hit a specific missing feature.

Take quiz
Which edition is free and open source?
Enterprise
Community
Teams
Ultimate
Undo migrations are generally offered in:
only the Community edition
no edition at all
the paid editions

17. How do you use Flyway with Spring Boot?

Add flyway-core (plus the database module, such as flyway-database-postgresql, for newer versions) to the build. Spring Boot auto-configures Flyway, and it runs migrate on startup before the JPA layer touches the database.

By default it reads scripts from classpath:db/migration, so place files in src/main/resources/db/migration. Tune it with spring.flyway.* properties.

spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
spring.flyway.baseline-on-migrate=false
spring.jpa.hibernate.ddl-auto=validate

Spring Boot waits for migrate to finish before building the JPA layer, so entities never see a half-updated schema. Set baseline-on-migrate only when adopting Flyway on an existing database.

Take quiz
Where does Spring Boot look for Flyway scripts by default?
src/test/flyway
classpath:db/migration
classpath:sql/scripts
Which Hibernate setting pairs well with Flyway-managed schemas?
ddl-auto=create-drop
ddl-auto=update on production
ddl-auto=validate
ddl-auto=random

18. How do you use the Flyway Java API?

Build a Flyway instance with the fluent configuration API, then call a command on it. This is useful when an application should migrate its own database at startup without Spring Boot.

Flyway flyway = Flyway.configure()
    .dataSource(&quot;jdbc:postgresql://localhost:5432/shop&quot;, &quot;app&quot;, &quot;secret&quot;)
    .locations(&quot;classpath:db/migration&quot;)
    .baselineOnMigrate(false)
    .load();

MigrateResult result = flyway.migrate();
System.out.println(&quot;Applied: &quot; + result.migrationsExecuted);

Other commands such as info(), validate(), and repair() are available on the same object.

Calling migrate() again is safe, since with nothing pending it does nothing. Let the FlywayException propagate at startup so the application never runs against an outdated schema.

Take quiz
Which method finishes building a configured Flyway object?
start()
compile()
build-all()
load()
Which call applies pending migrations through the API?
flyway.apply-all()
flyway.migrate()
flyway.deploy-now()
flyway.commit()

19. What is the difference between versioned and repeatable migrations?

A versioned migration has a unique version and runs once. A repeatable migration has no version and runs again every time its checksum changes. This single difference drives how you use them.

Aspect Versioned (V) Repeatable (R)
Filename V2__add_table.sql R__orders_view.sql
Runs Exactly once Whenever content changes
Order By version number After versioned, by description
Editing after apply Not allowed (checksum error) Expected and safe
Best for Tables, columns, indexes, data fixes Views, procedures, functions

Use CREATE OR REPLACE inside repeatable scripts so a rerun does not fail.

A practical rule: if rerunning the script is harmless and the latest definition should always win, make it repeatable. Otherwise make it versioned.

Take quiz
Which migration type may be edited after it has been applied?
Versioned
Baseline row
Both are blocked equally
Repeatable
Which runs last in a single migrate run?
Repeatable migrations
Versioned migrations
Undo migrations

20. How does Flyway order migrations?

Flyway sorts versioned migrations by version, comparing each dot or underscore separated part as a number. So 1.2 comes before 1.10, and 2 comes after both. Letters in file names do not affect order, only the version does.

After all pending versioned migrations, Flyway runs repeatable migrations, sorted alphabetically by description. Two migrations with the same version cause an error, because the version is the unique key.

V1__init.sql        -> 1st
V1.2__index.sql     -> 2nd
V1.10__audit.sql    -> 3rd
R__reports.sql      -> last

You can see the resolved order at any time with flyway info, which lists versions in the sequence Flyway will use.

Take quiz
Which version is considered newer?
1.2 is newer than 1.10
1.10 is newer than 1.2
They are equal
What happens if two migrations share the same version?
The newer file silently wins
Flyway reports an error
They run in parallel
Flyway renames one automatically

21. How does Flyway detect modified migrations?

When a migration runs, Flyway stores a CRC32 checksum of the script content in flyway_schema_history. On later runs it recalculates the checksum from the file and compares it.

If the numbers differ for a versioned migration, validation fails with a message like Migration checksum mismatch. Line endings and whitespace changes also alter the checksum, which is why mixed Windows and Linux line endings sometimes cause surprise failures. Repeatable migrations are the exception, because a changed checksum simply triggers a re-run.

The error message prints both the applied and the resolved checksum, so you can tell which side changed. Run flyway validate to see it without applying anything.

Take quiz
What does Flyway store to spot a changed script?
A full backup of the file
A CRC32 checksum
The Git author name
The file's last-opened time
Why might only whitespace edits break validation?
Flyway compares screenshots
Whitespace and line endings change the checksum
Whitespace affects table names
Flyway ignores content and checks owners

22. What is the purpose of flyway repair?

repair fixes problems in the schema history table so you can continue. It does not change your application tables.

It does two main things:

  1. Removes failed migration entries (on databases without transactional DDL, where a half-applied script leaves a failed row).
  2. Realigns stored checksums, descriptions, and types with the files currently on disk.

Only run it after you have understood the cause. If the failed script partly changed the schema, undo those changes manually first, otherwise the next migrate will fail again.

flyway repair

If a checksum change was intentional and harmless, such as a fixed comment, repair is the supported way to update the stored value. Note the reason in your commit message.

Take quiz
Does repair modify your business tables?
Yes, it recreates all tables
No, only the history table
Yes, it deletes old rows
Yes, it reorders columns
Before running repair after a failure you should:
clean up any partial changes the failed script left
delete the Flyway jar
rename every migration

23. When should you use baselineOnMigrate?

Use baselineOnMigrate=true when you run migrate against a non-empty schema that has no history table, and you want Flyway to baseline it automatically instead of failing.

It is convenient for rolling Flyway out across many existing databases in a pipeline. The risk is that it will baseline any non-empty schema, including one you pointed at by mistake, and then skip migrations at or below baselineVersion. For a one-time adoption, an explicit baseline command is safer, and the flag should be turned off afterwards.

flyway -baselineOnMigrate=true -baselineVersion=3 migrate

With the flag on, the first migrate inserts a baseline row at baselineVersion (default 1), then applies anything higher. Always confirm that version first.

Take quiz
baselineOnMigrate helps when migrate meets:
an empty schema with a history table
a failed network connection
a non-empty schema without a history table
What is the main risk of leaving baselineOnMigrate on permanently?
It slows down SQL parsing
It may baseline the wrong non-empty schema by accident
It removes checksums
It disables callbacks

24. What happens when a Flyway migration fails?

The outcome depends on whether the database supports transactional DDL. Each migration runs in its own transaction by default.

On PostgreSQL or SQL Server, a failure rolls the whole script back, nothing is recorded, and you fix the file and rerun. On MySQL or Oracle, DDL statements commit implicitly, so earlier statements in the script may already be applied. Flyway then records the migration as failed and refuses to run further migrations.

To recover: manually revert the partial changes, run flyway repair to remove the failed entry, correct the script, and run migrate again.

Either way the command exits non-zero, so a pipeline stops at that stage. Read the error for the script name and line before touching the database.

Take quiz
Why can a failed MySQL migration leave partial changes?
DDL statements commit implicitly there
Flyway ignores errors on MySQL
MySQL has no tables
Flyway always disables transactions
What is the usual recovery order after a failed, partly applied script?
Migrate again, then repair
Delete all data, then baseline
Revert partial changes, repair, fix script, migrate
Run clean on production

25. Why should applied migrations never be edited?

Because the migration is the historical record of how a database reached its current shape. If you edit it after it ran, databases that already applied the old version no longer match the file, and any new database would get a different result.

Flyway protects against this with checksums, so validation fails on the edited file. The correct approach is to add a new migration that makes the fix, for example an ALTER TABLE after a wrong column type. Editing is only acceptable for a script that has never left your own local database.

Enforce this in code review and CI, because validate will fail on every environment that already ran the original.

Take quiz
The correct way to fix a mistake in an applied versioned script is to:
add a new migration that corrects it
edit the old file and hope
delete the history table in production
rename the file to a lower version
Editing an applied migration causes environments to:
upgrade faster
drift apart and fail checksum validation
share one encrypted copy

26. How does Flyway handle transactions?

By default Flyway wraps each migration in its own transaction. If any statement fails, the transaction rolls back, as long as the database supports transactional DDL.

You can change the behaviour:

  • group=true runs all pending migrations in a single transaction.
  • mixed=true allows transactional and non-transactional statements in one run.
  • executeInTransaction=false in a script config file disables the transaction for that script.

Some statements, such as CREATE INDEX CONCURRENTLY in PostgreSQL, cannot run inside a transaction and need the non-transactional option.

Check how your database treats DDL before relying on rollback. Keep risky scripts small, so a failure leaves less to clean up, and test them on a copy first.

Take quiz
What is Flyway's default transaction scope?
One transaction per migration
One transaction per database server
No transactions at all
Which statement typically needs executeInTransaction=false?
SELECT 1
CREATE INDEX CONCURRENTLY in PostgreSQL
CREATE TABLE in a test schema
INSERT of a single row

27. When should you enable outOfOrder in Flyway?

outOfOrder=true lets Flyway apply a pending migration whose version is lower than the latest applied version. Normally such a script is ignored and validation flags it.

A common case is two branches: branch A merges V5 and deploys, then branch B merges V4. Without the flag, V4 is never applied. Enable it only when you accept that order of execution can differ between environments, and make sure scripts are independent of each other. Many teams avoid the problem by using timestamp versions plus careful merging.

flyway -outOfOrder=true migrate

After the late script runs, info shows it with the state Out of Order, so you can still see it ran later than its version suggests.

Take quiz
What does outOfOrder allow?
Skipping the history table
Applying a lower version after a higher one is already applied
Running two databases at once
Editing checksums freely
What is the main trade-off of outOfOrder?
It deletes older tables
It disables validation forever
It only works with Java
Execution order may differ between environments

28. How do you write a Flyway Java-based migration?

Create a class that extends BaseJavaMigration and put it in a package on a configured location. The class name follows the same naming rule as SQL files, with V, version, double underscore, then description.

package db.migration;

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import java.sql.Statement;

public class V3__Normalize_emails extends BaseJavaMigration {
    @Override
    public void migrate(Context context) throws Exception {
        try (Statement st = context.getConnection().createStatement()) {
            st.execute(&quot;UPDATE customer SET email = LOWER(email)&quot;);
        }
    }
}

Use Java when you need loops, conditionals, or calls to libraries, for example transforming rows in code.

Java migrations are compiled and must be on the classpath. They appear in the history table with type JDBC, and their checksum is only recorded if you override getChecksum().

Take quiz
Which class do Java migrations extend?
AbstractFlywayScript
SqlMigrationBase
BaseJavaMigration
JdbcRunner
Which method holds the migration logic?
migrate(Context context)
run()
execute-all()

29. What is the difference between Flyway and Liquibase?

Both are migration-based tools that track applied changes in a table, but they differ in how changes are written and in philosophy.

Aspect Flyway Liquibase
Change format Plain SQL (or Java) files XML, YAML, JSON, or SQL changelogs
Ordering File version in the name Order of changesets in the changelog
Tracking table flyway_schema_history DATABASECHANGELOG
Learning curve Very low, just SQL Higher, own changelog syntax
Database portability You write dialect-specific SQL Abstract change types can generate per-database SQL

Pick Flyway when your team is comfortable with SQL and wants simplicity. Pick Liquibase when you want database-neutral change definitions or richer conditional logic.

Take quiz
Which tool tracks changes in a table named DATABASECHANGELOG?
Liquibase
Flyway
Both identically
Flyway migrations are most commonly written as:
plain SQL files
XML changelogs only
binary patches
Excel sheets

30. How do you manage Flyway configuration across environments?

Keep the migration scripts identical everywhere and vary only the connection and environment settings. Three common techniques:

  1. Separate config files, for example flyway-dev.conf and flyway-prod.conf, passed with -configFiles.
  2. Environment variables such as FLYWAY_URL injected by the CI system.
  3. Named environments in flyway.toml, selected with -environment=prod.

Use placeholders for values that differ inside SQL, like schema names or grantee roles. Never keep passwords in files committed to Git.

A tidy layout is one shared sql folder plus a small config per environment. Use -configFiles to layer a base file with an environment override, so only changed keys are repeated.

Take quiz
What should differ between environments?
The SQL migration history itself
Connection details and placeholder values
The Flyway checksum algorithm
The version numbering scheme
Which option selects a named environment in flyway.toml?
-environment=prod
-profile-prod
-target=env
-site=prod.conf

31. How do you use Flyway with Docker?

Redgate publishes the flyway/flyway image. You mount your SQL folder and pass configuration as arguments or environment variables, which gives you a tool-free runner in CI.

docker run --rm \
  -v &quot;$PWD/sql:/flyway/sql&quot; \
  flyway/flyway \
  -url=jdbc:postgresql://db:5432/shop \
  -user=app -password=&quot;$DB_PASSWORD&quot; \
  migrate

In Docker Compose, add a Flyway service with depends_on the database, so migrations run once the database is healthy and before the application starts.

Pin the image tag, for example flyway/flyway:10, so builds stay reproducible. Extra JDBC drivers can be mounted into /flyway/drivers, and CI should check the container exit code to catch failed migrations. Use a named network so the container can reach the database.

Take quiz
Where is the SQL folder usually mounted inside the Flyway image?
/flyway/sql
/usr/share/db
/var/log/flyway
/home/app/migrations
In Docker Compose, the Flyway service should start:
before the network exists
after the database is ready
only after production deploy

32. How does Flyway prevent concurrent migrations?

When migrate starts, Flyway takes a lock so that only one process applies changes at a time. The mechanism depends on the database: it can be an advisory lock, a table lock on the schema history table, or a lock row.

A second instance, for example another application pod starting at the same time, waits for the lock, then finds that nothing is pending and exits cleanly. This is why running migrate from several replicas is generally safe, though many teams still prefer a single dedicated migration job to keep startup predictable.

In Kubernetes, an init container or a Helm pre-upgrade job is a common home for this single migration run.

Take quiz
What happens to a second instance that starts migrate while another holds the lock?
It runs the same scripts again at once
It drops the history table
It waits, then sees nothing pending
The lock is mainly meant to:
speed up SQL parsing
encrypt the migrations
stop two processes applying changes simultaneously
limit file sizes

33. Why is flyway clean disabled by default?

Because clean drops every object in the configured schemas and cannot be undone. A single wrong URL in a pipeline could wipe a production database.

Flyway therefore sets cleanDisabled=true by default in recent releases. Teams enable it only in local or ephemeral test environments, usually through a developer-only config file. In production configs, leave it disabled explicitly so a mistaken override is harder to make.

To use it deliberately, pass -cleanDisabled=false for one run or keep it in a local-only config. Some teams add a pipeline guard that rejects the flag when the URL points at production. The default is deliberately the safe one.

Take quiz
What is the reason clean is blocked by default?
It permanently removes all objects in the schemas
It is slower than migrate
It requires Java 8
It needs a paid license
Where is enabling clean considered reasonable?
Local or ephemeral test databases
Production
Shared staging with real customer data
Disaster recovery sites

34. How do you roll back a Flyway migration?

Flyway Community is a roll-forward tool: you fix problems with a new migration rather than reversing an old one. For many teams this is the safest approach, since data changes are rarely cleanly reversible.

The options are:

  • Undo migrations (U2__...sql) with flyway undo, available in paid editions.
  • Restore a backup or snapshot taken before the deployment.
  • Roll forward by writing a new versioned script that reverses the change.

Whichever you choose, test the rollback path on a copy of production data before release day.

Destructive changes, such as dropping a column, lose data that an undo script cannot bring back, so take a backup before the release.

Take quiz
Which approach does Flyway Community favor for fixing a bad change?
Editing the old script
Deleting the history table
Rolling forward with a new migration
Running clean on production
Which command reverses a versioned migration in paid editions?
flyway revert-all
flyway undo
flyway back

35. How do you integrate Flyway into a CI/CD pipeline?

Treat migrations like application code: they are reviewed in a pull request, tested automatically, and deployed by the pipeline using the same scripts that ran in earlier stages.

  1. Pull request: run flyway validate and a migrate against a throwaway database to prove the scripts apply cleanly.
  2. Build: package the SQL folder as an artifact, or bake it into a Docker image.
  3. Deploy: run flyway info to preview, then flyway migrate per environment before the application rollout.
  4. Verify: fail the stage if the exit code is non-zero, and publish the info output as a build record.
# GitHub Actions step
- name: Migrate database
  run: |
    docker run --rm -v &quot;$PWD/sql:/flyway/sql&quot; flyway/flyway \
      -url=&quot;$DB_URL&quot; -user=&quot;$DB_USER&quot; -password=&quot;$DB_PASSWORD&quot; migrate

Store credentials in the CI secret store and pass them as environment variables.

Take quiz
Which command is a good early pipeline check before deploying?
flyway clean
flyway baseline on prod
flyway validate
Where should the database password for the pipeline live?
Inside a SQL migration
In the Git repository's README
In a public config file
In the CI secret store

36. How do you migrate to a specific version using target?

Set target to a version and Flyway applies pending migrations only up to and including it. Anything higher stays pending.

This is useful to reproduce a bug at an older schema, stage a release in steps, or test an upgrade path. Special values are latest (default), current, and next.

flyway -target=2.5 migrate

Remember that the target also affects validation: migrations above the target are not treated as errors, they are simply not yet applied.

A typical use is a staged release: migrate to the last version the old application understands, deploy the app, then run the rest. Running info afterwards confirms what is still pending.

Take quiz
What does -target=2.5 do?
Deletes versions above 2.5
Renames files to 2.5
Applies pending migrations up to version 2.5
Locks the database at 2.5 forever
Which special value means apply everything available?
next-only
zero
latest
all-or-none

37. Explain the execution flow of flyway migrate?

When you run migrate, Flyway follows a fixed sequence. Understanding it helps when you debug unexpected behaviour.

flowchart TD
    A["Start migrate"] --> B["Connect and acquire lock"]
    B --> C{History table exists?}
    C -- No, empty schema --> D["Create history table"]
    C -- No, schema not empty --> E["Fail or baseline if baselineOnMigrate"]
    C -- Yes --> F["Validate applied migrations"]
    D --> G["Scan locations for scripts"]
    F --> G
    G --> H["Pick pending versioned migrations"]
    H --> I["Run each in a transaction and record result"]
    I --> J["Run changed repeatable migrations"]
    J --> K["Run afterMigrate callbacks and release lock"]

Callbacks such as beforeMigrate fire at the start, and beforeEachMigrate around every script. If a script fails, Flyway stops there, releases the lock, and returns a non-zero exit code. Scripts already committed stay applied.

Validation happens before any new script runs, which is why one edited old file blocks the whole deployment. That is intentional: Flyway stops rather than guessing.

Take quiz
What does Flyway do first if the schema is empty and has no history table?
Creates the history table
Runs clean
Aborts with a licence error
Deletes the SQL folder
Repeatable migrations in this flow run:
before the lock is taken
instead of versioned ones
after pending versioned migrations

38. How do you achieve zero-downtime migrations with Flyway?

Flyway only runs the scripts. Zero downtime comes from how you design them: every change must be compatible with both the old and new application versions during rollout. The standard pattern is expand and contract.

  1. Expand: add the new column or table as nullable, with no destructive change. Deploy migration first.
  2. Migrate data: backfill in small batches, keep old and new columns in sync.
  3. Switch: deploy the new application version that uses the new structure.
  4. Contract: in a later release, drop the old column with a new versioned migration.

Avoid long locks: create indexes concurrently where supported, add columns without volatile defaults on large tables, and never rename a column in one step while the old code is still running. Also run migrations before the application rollout, not inside every pod, so a slow script does not block startup.

Take quiz
In expand and contract, what happens first?
Drop the old column
Add new structures without removing old ones
Restart the database
A safe rename on a busy table usually involves:
renaming in place during peak traffic
running clean first
adding a new column, syncing, then dropping the old one later
disabling checksums

39. How do you introduce Flyway to an existing production database?

The goal is to put the current schema under version control without re-running history. A careful approach looks like this:

  1. Extract the current schema as a script, for example V1__baseline.sql, using your database's dump tool, and use it to build new dev databases.
  2. In production, run flyway baseline -baselineVersion=1 so Flyway records that version 1 already exists there.
  3. Add all further changes as V2 and above.
  4. Run flyway info and validate against a restored copy of production first.
flyway -baselineVersion=1 -baselineDescription=&quot;Initial prod state&quot; baseline

Verify the extracted script really recreates production's schema, otherwise new environments will drift from it. Paid editions can generate a baseline migration to help here.

Record the cutover in the runbook, including who ran baseline and when, so later audits can trace the starting point.

Take quiz
What does baseline at version 1 tell Flyway about production?
Version 1 is already in place, skip it
Delete everything older than 1
Run V1 again
Lock all tables
Before baselining production, you should first test the process on:
a developer's local notes
an empty unrelated database only
the live primary during peak hours
a restored copy of production

40. How do you troubleshoot a Flyway validate failed error?

Read the message first, because Flyway names the exact script and the cause. The common ones:

Message theme Likely cause Fix
Checksum mismatch An applied script was edited Revert the file, or if intentional and safe, run repair
Detected resolved migration not applied Lower version merged after higher one deployed Use outOfOrder or renumber
Detected applied migration not resolved locally Script deleted or wrong locations Restore the file or fix the path
Detected failed migration A previous run failed Fix partial changes, repair, rerun

Run flyway info to see states, and add -X for debug logs to confirm which locations Flyway actually scanned. Use ignoreMigrationPatterns only for known, understood cases. Check line endings too, since Git autocrlf is a classic source of surprise checksum errors.

Take quiz
A checksum mismatch most often means:
an already applied script was modified
the database is offline
the JDBC driver is old
the history table has no rows
Which flag prints detailed debug output from the CLI?
-quiet-only
-X
-debugfile=none

41. How do you handle large data migrations in Flyway?

Separate schema changes from bulk data work. A single UPDATE across hundreds of millions of rows can hold locks, bloat the transaction log, and make the deployment time unpredictable.

Better options:

  • Break the work into batches inside a Java migration, committing between batches (with a non-transactional setup if needed).
  • Run the heavy backfill as a separate job outside the deployment, and keep only the quick schema change in Flyway.
  • Add the new column first, backfill gradually, then add constraints in a later migration.
  • Test with production-sized data to measure runtime.

Avoid putting long-running scripts in the same release window as other changes. If a script must run non-transactionally, make it idempotent so it can be safely retried after a failure.

Take quiz
Why split bulk data work from schema changes?
Long locks and unpredictable deploy time
SQL forbids updates
Flyway cannot read large files
A script that must be retried safely should be:
encrypted
version-less
idempotent
auto-generated

42. How can you use Flyway in a multi-tenant architecture?

The right approach depends on the tenancy model. In both cases the same scripts must reach every tenant.

Model Approach
Database per tenant Loop over tenant connection details and run migrate for each, ideally in parallel with a concurrency cap
Schema per tenant Run migrate with schemas=tenant_a, then the next tenant, or use the Java API to iterate
Shared schema Run once; tenant id is a column, so no per-tenant migration is needed

for tenant in $(cat tenants.txt); do
  flyway -url=&quot;jdbc:postgresql://db/${tenant}&quot; -user=app migrate || exit 1
done

Track which tenants succeeded, since a failure part-way leaves tenants on different versions. Tenant-specific data should come from placeholders or callbacks, not separate migration files.

Parallel runs shorten the total time, but cap the concurrency so the database server is not overloaded.

Take quiz
In a schema-per-tenant model, how are tenants migrated?
Run it once for all tenants automatically
Edit the history table by hand
Use undo for each tenant
Run migrate once per tenant schema
A risk of looping over many tenants is:
Flyway deleting the loop
tenants ending up on different versions after a mid-loop failure
checksums becoming negative
the SQL folder being locked

43. How do you avoid version conflicts in team development?

Conflicts happen when two developers pick the same next number, for example both create V8. Flyway then fails with a duplicate version error.

Practical ways to avoid this:

  • Use timestamp versions such as V202610141530__add_index.sql, which almost never collide.
  • Keep one directory of migrations and let CI run validate on every pull request, so clashes surface before merge.
  • Enable outOfOrder in dev only, if branches routinely merge in a different order than they deploy.
  • Never renumber a file after it was merged and applied anywhere.

Agree on one convention for the team and write it in the contributing guide.

When a clash does slip through, the later branch should rename its file to a new version before merging. That is safe because the script has not been applied anywhere yet.

Take quiz
Why do timestamp versions help teams?
They remove checksums
They run faster
Two developers rarely pick the same value
They avoid the history table
Where is a good place to detect duplicate versions early?
In production at midnight
CI validation on pull requests
In a post-release survey

44. What is a custom MigrationResolver and when would you use it?

A MigrationResolver is a Flyway extension point that tells Flyway where migrations come from. The built-in resolvers find SQL files and Java classes; a custom one lets you supply migrations from somewhere else.

Examples include generating migrations from a template, loading them from a remote store, or building them from annotations or metadata. You implement the interface, return a list of ResolvedMigration objects, and register it with resolvers. Setting skipDefaultResolvers=true turns off the standard ones.

public class TemplateResolver implements MigrationResolver {
    @Override
    public Collection<ResolvedMigration> resolveMigrations(Context context) {
        // build and return ResolvedMigration objects
        return List.of();
    }
}

Most teams never need this; reach for it only when files and classes genuinely do not fit.

Resolved migrations still go through checksum validation, so generated content must be deterministic. If the output changes between runs, validate will fail.

Take quiz
What does a custom MigrationResolver provide to Flyway?
A new database driver
A faster checksum
A source of migrations beyond files and classes
Which setting disables the built-in resolvers?
skipDefaultResolvers
noBuiltinScan
resolverOff
disableLookup

45. How do you secure database credentials in Flyway?

Keep credentials out of migrations and out of Git. The URL, user, and password belong to the runtime environment, not the repository.

  • Pass them as environment variables (FLYWAY_PASSWORD) injected from your CI secret store.
  • Use a secret manager such as Vault, AWS Secrets Manager, or Azure Key Vault to fetch values at runtime, and note that paid editions also include resolvers for some of these.
  • Prefer short-lived or IAM-based credentials where the database supports them.
  • Give the migration account only the rights needed for DDL, and use a different, less privileged account for the application.

Remember that command-line arguments can be visible in process listings, so environment variables or secret files are safer than -password= typed inline.

Take quiz
Which is a safer place for the Flyway password in CI?
An injected environment variable from a secret store
A comment in V1__init.sql
A committed flyway.conf
A shared wiki page
Why separate the migration account from the app account?
Least privilege for the application
It speeds up queries
Flyway requires two accounts
It avoids checksums

46. How do you test Flyway migrations?

Test that scripts apply cleanly, and that the resulting schema and data behave as expected, before they reach shared environments.

  1. Fresh build: start an empty database (Docker or Testcontainers), run migrate, and confirm it succeeds.
  2. Upgrade path: restore a production-like snapshot at the previous version and migrate to the new one.
  3. Assertions: run integration tests or SQL checks for expected tables, constraints, and data.
  4. Validate: run validate to catch edited or missing scripts.
@Container static PostgreSQLContainer<?> db = new PostgreSQLContainer<>(&quot;postgres:16&quot;);

@Test void migrationsApply() {
    Flyway f = Flyway.configure()
        .dataSource(db.getJdbcUrl(), db.getUsername(), db.getPassword()).load();
    assertTrue(f.migrate().success);
}

Use the same database engine and major version as production, because SQL dialects differ.

Keep test-only seed data in a separate location, selected with a different locations value, so it never reaches production.

Take quiz
Why test against the same engine as production?
SQL dialects and DDL behaviour differ between databases
Flyway only supports one
It makes files shorter
Checksums depend on the engine name
Which upgrade test is most realistic?
Migrating a production-like snapshot from the previous version
Running only on an empty database
Running only a syntax linter

47. How do you use ignoreMigrationPatterns safely?

ignoreMigrationPatterns tells validation to tolerate certain migration states instead of failing. It replaces the older ignoreMissingMigrations and ignoreFutureMigrations flags. A pattern has the form type:state, for example:

Pattern Meaning
*:missing Ignore applied migrations whose file is not present locally
*:future Ignore applied migrations newer than anything local
repeatable:missing Ignore only missing repeatable migrations

flyway -ignoreMigrationPatterns=&quot;*:future&quot; validate

Use it sparingly, for known cases such as deploying an older branch to a database that a newer branch already upgraded. Broad patterns hide real drift, so scope them to a type and state, and remove them once the situation passes.

Review the setting at every upgrade. A pattern that lingers after its cause is gone can silently hide a real problem, so remove it as soon as the situation passes.

Take quiz
What does the pattern *:future cover?
Pending scripts
Applied migrations newer than any local script
Callbacks
Why should the patterns be narrow?
They run slower
Broad patterns can hide real schema drift
They break Java
They delete rows

48. What does Flyway Desktop add to the command-line workflow?

Flyway Desktop is Redgate's graphical tool that sits on top of the same migration engine. It does not replace the CLI; the migrations it produces are standard Flyway scripts you run in your pipeline.

Its main value is helping developers generate migration scripts from schema changes. You edit a development database, compare it with a schema model kept in source control, and Desktop produces the versioned script for you. It also helps with schema comparison, drift review, and shadow databases for building and checking scripts.

Teams often use Desktop locally to author changes and the CLI or Docker image in CI to deploy them. Some of these features are licensed, so check the edition you have.

Feature availability depends on your licence and version, so confirm it in the Redgate documentation.

Take quiz
How are Flyway Desktop migrations deployed in a pipeline?
Only by clicking the app on production
As binary patches
Through email attachments
As standard Flyway scripts via the CLI or Docker
What is a main benefit of Flyway Desktop?
Replacing the history table
Generating migration scripts from schema differences
Hosting your database
Compressing backups

49. Which is better and why: SQL or Java migrations in Flyway?

SQL is the default and the better choice for most changes. Java is a specialist tool for logic that SQL cannot express well.

Aspect SQL migration Java migration
Readability Anyone with SQL can review it Needs Java knowledge
Tooling Easy to run in a DB client Needs build and compile step
Logic Limited to what the dialect allows Loops, libraries, conditions
Portability Dialect-specific Can adapt through JDBC code
Typical use DDL, simple data changes Complex data transforms, calling services

Start with SQL. Move to Java when you need row-by-row transformation, batching with commits, or reuse of application code. Keep Java migrations free of dependencies on changing application classes, because they must keep working years later.

Whichever you pick, write the rule in the team guidelines so every new migration follows it.

Take quiz
When is a Java migration the better fit?
Creating a simple table
Complex row-by-row data transformation
Adding one index
Renaming a file
What risk comes with Java migrations that call application classes?
Flyway blocks them
They skip checksums
The classes may change, breaking old migrations

50. Explain the lifecycle of a Flyway migration from commit to production?

A migration moves through the same stages as any other code change, with extra checks because it alters shared state.

sequenceDiagram
    participant Dev as Developer
    participant Git as Git / PR
    participant CI as CI pipeline
    participant Test as Test DB
    participant Prod as Production DB
    Dev->>Git: Commit V12__add_index.sql
    Git->>CI: Trigger build
    CI->>Test: flyway validate and migrate on fresh DB
    Test-->>CI: Success
    CI->>Prod: flyway info (preview pending)
    CI->>Prod: flyway migrate
    Prod-->>CI: Row added to flyway_schema_history
  1. Author: write a new versioned script, never editing old ones.
  2. Review: a teammate checks SQL for locks, data impact, and naming.
  3. Verify: CI builds a fresh database and upgrades a snapshot.
  4. Deploy: the pipeline runs migrate with the checksums recorded in the history table.
  5. Observe: confirm with info, and keep the previous version available for roll-forward or restore.

If production fails, the failed script is visible in the history table and the logs, which is the first place to look.

Take quiz
Which stage records the checksum in the history table?
The deploy-time migrate run
Code review comments
Git commit message
What should CI do before production migrate?
Validate and migrate on a fresh or snapshot test database
Skip all tests
Run clean on production
Rename all scripts
«
»

Comments & Discussions