Flyway

Language: Java

Database/Migration

Flyway was created to simplify database version control and continuous integration workflows. It enables developers to maintain consistent database schemas across environments, ensures smooth migrations, and integrates easily with Java applications and build tools. Flyway is widely used in enterprise applications, microservices, and automated deployment pipelines.

Flyway is an open-source database migration tool for Java that allows developers to version, manage, and automate database schema changes. It supports SQL-based migrations as well as Java-based migrations for complex transformations.

Installation

maven: Add dependency in pom.xml: <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>10.15.0</version> </dependency>
gradle: Add dependency in build.gradle: implementation 'org.flywaydb:flyway-core:10.15.0'

Usage

Flyway allows defining migrations as SQL scripts or Java classes, tracks which migrations have been applied, and ensures the database is up-to-date. It supports multiple databases such as PostgreSQL, MySQL, Oracle, SQL Server, and SQLite.

Basic Flyway configuration

import org.flywaydb.core.Flyway;

Flyway flyway = Flyway.configure()
    .dataSource("jdbc:postgresql://localhost:5432/mydb", "user", "password")
    .load();
flyway.migrate();

Configures Flyway with a PostgreSQL database and applies all pending migrations.

SQL-based migration

-- V1__create_users_table.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

Defines a SQL migration script named with Flyway's versioned naming convention (V1__).

Java-based migration

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

public class V2__Add_email_to_users extends BaseJavaMigration {
    @Override
    public void migrate(Context context) throws Exception {
        try (Statement stmt = context.getConnection().createStatement()) {
            stmt.execute("ALTER TABLE users ADD COLUMN email VARCHAR(255)");
        }
    }
}

Defines a Java-based migration to add a column to the users table.

Undo migration

-- U2__remove_email_from_users.sql
ALTER TABLE users DROP COLUMN email;

Defines an undo migration script to revert a previous migration if needed.

Baseline an existing database

Flyway flyway = Flyway.configure()
    .dataSource("jdbc:mysql://localhost:3306/mydb", "user", "password")
    .baselineVersion("1")
    .baselineOnMigrate(true)
    .load();
flyway.baseline();

Sets a baseline for an existing database to start managing migrations without reapplying old scripts.

Error Handling

FlywayException: Occurs if a migration fails or the database is in an inconsistent state. Inspect migration logs and fix the SQL/Java scripts.
ValidationException: Occurs when the applied migrations do not match the migration history. Use repair() cautiously to fix metadata.
SQLException: Occurs for database-level errors. Check connection settings, SQL syntax, and database compatibility.

Best Practices

Use versioned migrations (V1__, V2__, ...) for schema changes to maintain order.

Keep SQL scripts small and atomic to reduce risks during migrations.

Store migration scripts in source control alongside application code.

Test migrations in a staging environment before production deployment.

Use Java-based migrations only when complex logic or conditional operations are required.