Database Migrations — Flyway and Liquibase in Spring Boot
Fast recall
Quick revision
Core answer
id + author per changeset. Both track applied migrations in a metadata table (flyway_schema_history or DATABASECHANGELOG) so each migration runs exactly once. Never edit an applied migration — the checksum mismatch refuses startup. For zero-downtime deploys, use the expand-contract pattern: split breaking changes into multiple backwards-compatible steps across releases. Pair migrations with `spring.jpa.hibernate.ddl-auto=validate` so Hibernate verifies the live schema matches entity mappings.Whether the candidate understands schema migration versioning, immutability of applied scripts, and the role of migrations in CI/CD
Modifying an already-applied migration script — Flyway detects the checksum mismatch and refuses to start
Discuss expand-contract for zero-downtime, repeatable migrations, baseline for legacy DBs, big-table DDL, and pairing migrations with `ddl-auto=validate`
Interview-ready guide
Interview answer
Migration tools turn schema changes into versioned, repeatable scripts that run automatically at startup.
Flyway — version-based:
- Scripts named
V1__create_orders.sql,V2__add_index.sql - Flyway tracks applied migrations in
flyway_schema_history - At startup, applies all pending scripts in version order
- Once applied, a script is immutable — Flyway stores a checksum
Liquibase — changeset-based:
- XML, YAML, SQL, or JSON changelogs
- Each changeset has unique
id+author - Supports automatic rollback for simple changes
- Better for multi-database portability and rollback requirements
Spring Boot integration:
- Both auto-configure — drop the starter, place files in
db/migrationordb/changelog - Migrations run at startup before the app accepts traffic
- A failed migration blocks startup — safe for catching problems early
Production discipline:
- Pair with
spring.jpa.hibernate.ddl-auto=validateso Hibernate confirms entity mappings match - Use Testcontainers in CI to apply migrations against the real database engine
- For zero downtime, use the expand-contract pattern — split breaking changes across multiple deployments
Database Migrations — Flyway and Liquibase in Spring Boot
Direct Answer
Flyway and Liquibase manage schema changes as versioned migration scripts applied automatically at application startup. Flyway uses SQL files named V{version}__{description}.sql with a strict naming convention. Liquibase uses XML/YAML/JSON changelogs with id + author per changeset. Both track applied migrations in a metadata table (flyway_schema_history or DATABASECHANGELOG) so each migration runs exactly once. Never edit an applied migration — the checksum mismatch refuses startup. For zero-downtime deploys, use the expand-contract pattern: split breaking changes into multiple backwards-compatible steps across releases. Pair migrations with spring.jpa.hibernate.ddl-auto=validate so Hibernate verifies the live schema matches entity mappings.
Code Example
Both tools track schema changes in a version table and apply pending migrations at startup. Flyway prefers plain SQL; Liquibase prefers an abstract DSL (XML/YAML/JSON) that generates SQL per dialect.
-- src/main/resources/db/migration/V1__init.sql (Flyway)
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- src/main/resources/db/migration/V2__add_orders.sql
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
total NUMERIC(10,2) NOT NULL
);
CREATE INDEX idx_orders_user ON orders(user_id);
# Flyway config — pure SQL, DB-specific syntax allowed
spring:
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
validate-on-migrate: true
# db.changelog-master.yaml (Liquibase) — dialect-independent
databaseChangeLog:
- changeSet:
id: 1-create-users
author: ravi
changes:
- createTable:
tableName: users
columns:
- column: { name: id, type: bigint, autoIncrement: true, constraints: { primaryKey: true } }
- column: { name: email, type: varchar(255), constraints: { nullable: false, unique: true } }
rollback:
- dropTable: { tableName: users }
- Flyway assumes migrations are immutable once applied — fixing a typo means a new
V4__fix.sql, never editingV3__*.sql. It stores a checksum inflyway_schema_historyand fails fast on tampering. - Liquibase supports automatic rollback (each changeset declares its inverse) and has richer refactoring primitives (rename column, split table). Flyway rollbacks are a paid Teams feature.
- Both run before the JPA/Hibernate schema validator, so entity columns should match what migrations produced. Disable Hibernate's
ddl-autoin production (validateonly) and let the migration tool own the schema. - Rule of thumb: choose Flyway if your team writes native SQL comfortably and uses one database dialect; choose Liquibase for multi-dialect products or heavier refactoring needs.
Common Mistakes & Pitfalls
Modifying an already-applied migration script — Flyway detects the checksum mismatch and refuses to start
Check your understanding
Answer these without looking back at the article.
- How do you recover from a failed Flyway migration in production?
- What's the right way to add a `NOT NULL` column to a table with millions of existing rows?
- When would you prefer Liquibase over Flyway for a Spring Boot project?
- How do you test migrations against the real database before merging?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.