Database Migrations with Flyway

Evolve your schema safely with versioned SQL migrations . Drop V1__init.sql and V2__add_col.sql under db/migration and Spring Boot runs them automatically on startup.

Learn Database Migrations with Flyway in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Before You Start

You should have built a complete REST API and understand how Spring Boot connects to a database via a DataSource and JPA entities.

What You'll Learn

The Big Idea — Version Control for Your Schema

💡 Analogy: Git records every change to your code as an ordered series of commits. Flyway does the same for your database : each migration ( V1 , V2 , V3 ...) is a commit to the schema, applied in order and recorded in history. Anyone can replay the whole sequence from scratch and arrive at exactly the same database.

You describe each change once, as a script; Flyway guarantees it runs everywhere, exactly once, in order.

1️⃣ Your First Migration: V1__init.sql

Place SQL files under src/main/resources/db/migration . The first one creates your initial tables. Flyway applies it once and records it.

2️⃣ Evolving the Schema: V2__add_col.sql

Never edit an applied migration — add a new one. Flyway sees version 2 is higher than the applied version 1 and runs it on the next startup.

3️⃣ Configuring Flyway with spring.flyway.*

Flyway is auto-configured the moment it is on the classpath. Tune it with spring.flyway.* properties — including baseline-on-migrate for adopting an existing database.

4️⃣ Repeatable Migrations (the R prefix)

Repeatable migrations have no version and re-run whenever their checksum changes, after all versioned ones. They suit views, functions and procedures you keep in sync.

5️⃣ The Idea, Concretely

To make the apply-once-then-skip behaviour tangible, here is a plain-Java stand-in modelling the version history Flyway keeps — with real output.

🧠 Quick Recall

Answer: on the classpath under db/migration — i.e. src/main/resources/db/migration .

Answer: it reads the flyway_schema_history table and applies only newer versions.

Answer: migrations are explicit, reviewable, ordered and reproducible; ddl-auto=update guesses and never drops columns.

Common Errors

Pro Tips

📋 Quick Reference

Concept

Form / property

Note

location

classpath:db/migration

default scan path

versioned

V2__add_col.sql

runs once, in order

repeatable

R__view.sql

re-runs on checksum change

history

flyway_schema_history

tracks applied versions

baseline

spring.flyway.baseline-on-migrate

adopt existing DB

validate

ddl-auto=validate

prod schema check

📚 Resources / Keep Learning

❓ Frequently Asked Questions

🎉 Lesson Complete!

You now know how Flyway applies versioned SQL migrations on Spring Boot startup, how the flyway_schema_history table tracks what has run, how to configure it with spring.flyway.*, what repeatable migrations and baselining are for, and why migrations beat ddl-auto=update in production.

Next up: API Docs with OpenAPI & springdoc — auto-generating interactive documentation for your endpoints.

Practice quiz

What does Flyway do for a Spring Boot application?

  • Applies versioned database migrations automatically
  • Compiles SQL to Java
  • Caches HTTP responses
  • Generates REST controllers

Answer: Applies versioned database migrations automatically. Flyway is a database migration tool: it applies versioned SQL scripts to bring your schema to the desired state, and Spring Boot runs it on startup.

Where does Flyway look for migration scripts by default in a Spring Boot app?

  • the project root
  • META-INF/sql
  • src/main/resources/db/migration
  • src/main/java/migrations

Answer: src/main/resources/db/migration. By default Flyway scans classpath:db/migration, which maps to src/main/resources/db/migration in a standard Spring Boot project.

Which file name is a valid versioned migration?

  • migration-1.sql
  • V1__init.sql
  • 1-init.sql
  • init_v1.sql

Answer: V1__init.sql. Versioned migrations use the form V<version>__<description>.sql, e.g. V1__init.sql, with a capital V, the version, two underscores, then a description.

What is the flyway_schema_history table used for?

  • Caching query results
  • Storing application data
  • Logging HTTP requests
  • Tracking which migrations have already been applied

Answer: Tracking which migrations have already been applied. flyway_schema_history records every applied migration with its version, checksum and status so Flyway knows what still needs to run.

When does Spring Boot run Flyway migrations by default?

  • Automatically at application startup
  • Only on the first HTTP request
  • Never, you call it manually
  • On a nightly schedule

Answer: Automatically at application startup. With Flyway on the classpath, Spring Boot auto-runs pending migrations during application startup before the app is ready to serve traffic.

Which prefix marks a repeatable migration?

  • B (e.g. B__baseline.sql)
  • R (e.g. R__create_view.sql)
  • V (e.g. V1__create_view.sql)
  • U (e.g. U1__undo.sql)

Answer: R (e.g. R__create_view.sql). Repeatable migrations use the R prefix and have no version. They re-run whenever their checksum changes, which suits views and stored procedures.

Which statement about ddl-auto=update in production is correct?

  • It is required by Flyway
  • It is the safest option
  • It reliably drops unused columns
  • It can silently alter the schema and never drops columns, so migrations are preferred

Answer: It can silently alter the schema and never drops columns, so migrations are preferred. ddl-auto=update guesses schema changes, applies them unpredictably, and cannot handle data migrations or column removal, so it is unsafe for production. Versioned migrations are explicit, reviewable and repeatable.

What is baselining in Flyway?

  • Disabling migrations
  • Deleting all data
  • Marking an existing populated database at a starting version so Flyway can manage it going forward
  • Renaming the schema

Answer: Marking an existing populated database at a starting version so Flyway can manage it going forward. Baselining tells Flyway that an existing database is already at a given version, so it only applies migrations newer than that baseline instead of trying to recreate the whole schema.

Which property prefix configures Flyway in application.properties?

  • spring.datasource.*
  • spring.flyway.*
  • spring.migration.*
  • flyway.boot.*

Answer: spring.flyway.*. Flyway settings in Spring Boot use the spring.flyway.* prefix, for example spring.flyway.enabled, spring.flyway.locations and spring.flyway.baseline-on-migrate.

What does Liquibase represent in this context?

  • An alternative migration tool to Flyway, often using XML/YAML changelogs
  • A replacement for the JVM
  • A logging framework
  • A web server

Answer: An alternative migration tool to Flyway, often using XML/YAML changelogs. Liquibase is the main alternative to Flyway. It describes changes in XML, YAML, JSON or SQL changelogs and is also auto-integrated by Spring Boot.

Continue this course