Flyway in Spring Boot: Step-by-Step tutorial with Maven

 

Transcript:

Hi friends. In this video I'll show you how to use Flyway with Spring Boot and Maven for database migrations, watch the whole video or click on the timeline to jump to the section you need. I'm not going to explain the whole structure of the project. To save time, you can browse it in the GitHub repo, the link is posted in the description. Basically, it's a CRUD application like pet clinic, but instead of owners, we have civilians and instead of pets we have implants that these civilians implant into themselves. Cyberpunk themed, of course.

Alright, to get started with the Flyway and Spring Boot, we need several dependencies. Spring Boot Starter Data, GPA, Docker Compose because I'm going to run Postgres SQL instance in a Docker container, but of course you can run it locally. We also need the dependency on Postgres SQL and of course on Flyway. So there is the Flyway core. And flyway for Postgres SQL. Let's look briefly at the composed yaml file. It's pretty simple. We are just spinning up the Postgres container called Neur Watch db. We are specifying the user password and DB ports a volume to store our data. And the network. And now the application properties. So here we also specify URL, username, password, and the driver for postgre SQL. We also disable hibernate because Flyway is going to manage our schema. So hibernate, DDL auto, non and optional. You can show SQL with a Spring JPA show, SQL True. Last but not least, the Let's Enable Flyway Spring Flyway enabled True and Spring Flyway locations ClassPass DB migration. This is the directory where we are going to store our database migration files. Flyway supports four types of migrations. Version, repeatable, baseline, and undo. Let's look at all of them. Let's start with version migrations. They are applied on the ones in strict version order, kinda like Git commits. There's a naming convention. The name starts with B, then it's followed by the unique version two underscores and the description. When you run database migrations with Flyway for the first time, flyway creates a separate table in your database. Called the Flyway schema history. This table tracks which version migrations have already been applied based on their check sum. So the most important rule, never change, migration piles. If you need to introduce some changes, just write a new file. Alright, let's start with the creating our first migration. Let's call it V one, create tables. Flyway works with SQL. So you can write migrations in a familiar SQL dialect for your database. In this case, we are using Postgres. So we are writing migrations for Postgres. Everything's totally familiar, right? Create table a constraint and so on. Now run your application. In the console you'll see a log. Let's look at it. So here we see that the. Flyway schema history doesn't exist yet. Flyway validated one. Migration. It created the Flyway schema history table. Migrated to schema to version one, create tables and successfully applied one migration. Now, if we. Look at the structure of our database. We'll see that the database was successfully created and populated with necessary tables. Civilian Cyberware implant session. And as you can see, Flyway schema history. Let's look at this table more closely. So here we see the. Version, the description, the name of the script and the checksum. Let's create another version, migration file. Let's go it V two seed sample data and populate it with test data. Run the application again. You'll see that flyway. Migrated our schema to version two seed sample data. It applied one migration, and now the database is at version two. And if you look below, we'll see that the data was indeed inserted because now we get the information about the civilians in the console.

Next up, repeatable migrations. Repeatable migrations. Are reapplied every time they are checked on changes. The naming convention is the following, without a version, double underscore and description When the migrations are run, repeatable migrations are always applied, lost, usually repeatable. Migrations are used to create or update views procedures, or to perform. Bulk reloads of reference data. Let's look at the example. We'll create a repeatable migration which recreates a view joining all three tables every time we run migrations. How do we achieve that? Well, it is actually quite simple. You use the placeholder. With a timestamp. And so the migration runs every time because the timestamp place holder changes the check sum. As a result, flyway will recreate this view and update the statistics on every migration run. So here it is, our migration file R that will underscore implant summary review. In the beginning, you can see the. Placeholder Flyway timestamps. We'll talk a little bit more about placeholders later on. And there's also the comment that it is a repeatable migration. Here again, you use familiar SQL to join all three tables. Run your application again and refresh the schema of your database. You will see that we have a new view called B Implant Summary with the columns from all the tables.

Now let's talk about baseline migrations. Baseline migration is a single migration that represents the state of your database. After all of the version migrations have been applied, the naming convention is the following B db version, double underscore, and the description, for instance file B five. My database represents, um, the state of the database. After applying all version migrations up to and including version five, if you use Flyway on a new database, it picks up the latest baseline file marks every version, migration, which is lower than this baseline as ignored and starts from the baseline from this snapshot of the database. However, if the database already has a Flyway history. Baseline files are skipped. Baseline files do not conflict with the future v migrations, and they just speed up the installation of the database. So, for instance let's add one more version, migration, V four, add extra columns. Let's add a couple of columns to the civilian. Cyberware tables. And after that, that's a right baseline migration file. B five, double underscore baseline after schema updates. So here we create a snapshot of a database after the fourth version migration. You can see here that we, again, create all the tables, but this time with all the updates that we have introduced. As a result, if you run Flyway with a new database, it'll start at version five and it will skip version migrations, so on to and so on. But you can after that create version migrations again and change database schema just as we used to do. So baseline is a baseline.

Now, briefly about the under migrations. Under migrations are supported in Flyway teams only. So this is the commercial offering of Flyways and under migration, undos the effects of the version. But the same version. So the naming convention is you, the number of the version migration that it corresponds to, to underscores, and the description undo migrations work under the presumption that the whole migration succeeded and should be undone. But in some cases, migration can fail at, uh. Some points. So for instance, you have five statements and the statement two has failed, but you don't know that undo migrations are not really helpful in such situations. Also, one undo file rolls back. Just the last version, this case V two. And if you need to undo more version migrations, you add more under files. The alternative for Community Edition of Flyway and maybe even better alternative to undos is a forward fixed migration. So you are right, a new version, migration, describe it, and then remove all the necessary schema changes or data.

There if you are familiar with the Libc base, you know it has preconditions statements that must be fulfilled before the migration is run. Flyway doesn't have the libc base style preconditions. But there are several alternatives. You can write conditional statements. For instance, create index, if not exists, you can use PostgreSQL Do, which executes anonymous code block, for instance. Uh, let's uh, add new version migration for creating an index. Only when both table and column exist. That's called B five Index Birth rate if table exists, and here is the DO Postgres file. As you can see, we have the precondition if exists, and then we apply the migration. You can also use placeholders. We have already seen a placeholder in a repeatable migration file with a timestamp, but placeholders can also be used to create preconditions. We can declare the placeholders in the application properties file, for instance, spring Flyway placeholders, and then the name of your placeholder in this case. Seat demo data, and then you set it to true or false. Then after that you reference this placeholder inside the migration file. Let's see. Let's create a new migration, V six conditional demo seat. And here again we have the Postgres DO file. But instead of writing the lengthy precondition ourselves, we simply use the placeholder with the, if so, if the demo data is true, then we. Insert the demo data here. Flyway will substitute the seed demo data with True or walls at runtime. As a result in non-production environment, you can get demo rows, but in production. You can set this placeholder to false and the block evaluates the IF statement and if the placeholder points to false, then it immediately exits and leaves the database untouched.

Now let's see how we can use. Flyway from the command line interface. Let's add to the Flyway Maven plug into our OT XML. We need to configure it a bit. Basically you need to specify the user, the password, the URL and the schema. But the schema is not obligatory, so the necessary is user password and URL. After that, you can run the Flyway commands. Flyway supports five basic commands to manage database migrations. Info prints information about the current database version, pending migrations, run migrations, and so on. Migrate migrates a database schema to the current version baseline baselines, the current database schema. It is useful when you need to start using Flyway. With the existing database, validate validates the current database schema repair repairs metadata table clean drops all objects in a configured schema. Never, never use it in production. For instance, let's run Maven Libc Liquid Base. Here we can see the summary of the statistics for our database migrations. We can see the info about the version migrations that were applied. We used the baseline migration. So all the migrations below baseline are ignored. This command is very useful to know what's going on with your database migrations.

And finally, let's see how we can use Flyway in ci. To run database migrations. We are going to use GitHub actions for that. Before we write our GitHub action workflow, let's adjust to the plugin settings a little bit. So here we removed the schema and uh, we specify to the. Placeholders that we have, the seed demo data, we set it to true in this case because it's demo. And another one is build a timestamp. This is going to be our custom placeholder. I'll explain why in a second. So what it is, what is the build timestamp we need to change the timestamp place holder in the repeatable migration so that the migration. In CI doesn't fail. So add this new placeholder to the application properties. And after that, change the timestamp to custom placeholder in a repeatable migration file. Okay, and now we can move on to the workflow file. What do we have here? The file states that we run migrations on push to the main branches, and here is our workflow file. Let's see what's going on here. So here we have the name Flyway Migrations. That's the workflow's name that's going to be displayed in the action tab on workflow Dispatch. Push to branches main means that the workflow is automatically triggered every time the push to the main branch is performed. The concurrency block with this block, we verify that GitHub will not start two runs of this workflow on the same branch at once. So if this happens, then the older job runs and the new jobs queue. Okay? And then we have the jobs. Here we define only one job. It's called migrate. We spin up the Ubuntu VM, start a Postgres service next to the VM and specify the environmental variables for Postgres DB user and password. Then we verify that the container. Up and running and it is healthy. And uh, after that we proceed with the workflow. Then we specify some environmental variables for Flyway, URL, user and password. Then we specify the placeholder that we have built. Timestamp. It's our custom placeholder. In this case it stays constant for this run, but it'll change the next run. Then we just check out the repository process resources, set up the JDK. I'm using libc JDK recommended by Spring, configure J Home, and enable Maven dependency caching. Then we run Flyways. Uh, migrate and validate commands. Migrate, creates the schema history table and applies all pending v and r scripts. The validate command checks that the checks sums in the database match all the applied files. And finally, we deploy the application. In this case, this is just a placeholder for demonstration. But anyway, the deployment step runs. Uh, after all the steps in the workflow were successfully completed.

In this video, we looked into integrating Flyway with a Spring Boot and Maven. Don't forget to like this video, subscribe to our channel, and until next time.

Summary

The video shows how to use Flyway with Spring Boot and Maven for database migrations in Postgres via Docker. It explains versioned, repeatable, and baseline migrations, placeholders for conditions, and best practices like not editing old files. The author also demonstrates running Flyway with Maven and setting it up in GitHub Actions for CI/CD.

About Catherine

Java developer passionate about Spring Boot. Writer. Developer Advocate at BellSoft

Social Media

Videos
card image
Jul 15, 2025
Java Downgrade Challenge: From JDK 8 to 1.1 (Part 2)

In Part 2 of the Java Downgrade Challenge, we continue our journey — now from Java 8 all the way to Java 1.1. No streams, no lambdas, no generics, no collections — and at one point, we even boot up Windows 98. If you thought Part 1 was painful, this one unwinds Java history line by line. By the end, the familiar Java from today will be almost gone.

Videos
card image
Jun 27, 2025
5x Smaller Java Docker Images — 2025 Optimization Guide

In this video, I’ll show you how to make your Java Docker images 5 TIMES SMALLER. You’ll see the full process, from a heavy 587MB container to a lean 116MB image, ready for production.

Further watching

Videos
card image
Aug 27, 2025
Buildpacks for Spring Boot

Buildpacks for Spring Boot: no Dockerfiles, no hassle — just production-ready container images in one command. Tired of maintaining Dockerfiles? In this tutorial, you’ll learn how to use buildpacks to create optimized Spring Boot containers — fast, secure, and cloud-ready — with just one command. We’ll show what happens under the hood: automatic dependency detection, layered image creation, memory tuning, SBOM generation, and how to tweak builds with just a few plugin options. Need faster startup, smaller image size, or JFR monitoring? Buildpacks can handle it — and we’ll show you how.

Videos
card image
Aug 14, 2025
Stop Using DTOs – A Cleaner Way for Your Java APIs

Still creating DTOs for every API in your Spring Boot project? You might be overcomplicating things. In this video, we show why DTOs aren’t always necessary and how to replace them with @JsonIgnore, @JsonView, and Jackson Mixins. You’ll see real examples of hiding sensitive fields, creating role-based views, and cutting boilerplate — all while keeping your API safe, clean, and easy to maintain.

Videos
card image
Aug 6, 2025
GraalVM for Java Developers: The Ultimate Beginner’s Guide

What is GraalVM and how can it improve your Java applications? In just 10 minutes, this video explains the three main components of GraalVM — the JIT compiler, Native Image, and Polyglot API. Learn how to boost performance, reduce startup time, and combine multiple languages in one app. Whether you’re building microservices, serverless apps, or just exploring modern JVM tooling, this is your quick-start guide to GraalVM.