Foundation · Build

Database Migrations with Flyway

Versioned SQL scripts turn schema changes into reviewed, repeatable artifacts—Hibernate validates, Flyway evolves.

Primary source: Spring Boot 3.5: Flyway Database Migrations

20 min

Lesson 2 of 17

1d streak

The Architectural Question

ddl-auto=update performs dialect-dependent schema changes without a reviewed migration history. It cannot express deliberate renames or data transformations, provides no reliable rollback path, and cannot guarantee that environments converge.

What this guide proves

  • Write versioned migrations that run once, in order, everywhere
  • Keep ddl-auto at validate so code never improvises schema
  • Plan forward-only changes for zero-downtime deploys

Immutable schema migrations vs hibernate ddl-auto

Using spring.jpa.hibernate.ddl-auto=update in production is a critical liability: Hibernate may lock tables, drop constraints, or fail to apply changes safely across clustered instances. Flyway provides deterministic, auditable, and version-controlled SQL migrations.

Architectural Boundary · Do Not Confuse

Concept A

hibernate.ddl-auto=update

Concept B

Flyway Versioned Migrations (V1__init.sql)

Hibernate ddl-auto inspects entity mappings and attempts to alter the live schema dynamically on startup. It cannot safely express deliberate column renames, data migrations, or index tuning. During application startup, Flyway applies pending versioned migrations in numeric version order and records their versions and checksums in flyway_schema_history.

Flyway file naming rules and runtime execution

PrefixSeparatorVersion / DescriptionExample File Name
V__ (double underscore)Versioned: runs once, checksum validatedV1__create_orders_table.sql
U__ (double underscore)Undo: rollbacks (Flyway Teams feature)U1__undo_orders_table.sql
R__ (double underscore)Repeatable: re-runs whenever checksum changesR__create_order_summary_view.sql
src/main/resources/db/migration/V1__create_orders_table.sql
CREATE TABLE orders (
    id UUID PRIMARY KEY,
    customer_id UUID NOT NULL,
    total_amount NUMERIC(12, 2) NOT NULL,
    status VARCHAR(32) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_orders_customer_id ON orders(customer_id);

Break it deliberately: modifying an already executed migration

Terminal / Diagnostic Output
org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
Migration checksum mismatch for migration version 1
-> Applied to database : -182749102
-> Resolved locally    : 492817261

Immutable rule

Never edit an existing versioned migration file that has been deployed. To alter a table or add an index, always create a new sequential version file (e.g. V2__add_status_index.sql).

Active Recall Checkpoint

What should spring.jpa.hibernate.ddl-auto be set to when using Flyway in production?

Hint: Consider whether Hibernate should alter the database schema.

Show answer & explanation

Set spring.jpa.hibernate.ddl-auto=validate. This forces Hibernate to verify that your Java @Entity mappings match the Flyway-managed database schema exactly without mutating anything at runtime.

Production configuration baseline for Flyway

Use it when

Always use Flyway or Liquibase for relational databases in staging and production environments.

Reconsider when

Use ddl-auto=create-drop strictly in short-lived in-memory unit tests (H2) that boot and tear down per test run.

Runtime Architecture & Flow

Resolution model

Configuration resolution checklist

  1. 1

    Write versioned migrations that run once, in order, everywhere

  2. 2

    Keep ddl-auto at validate so code never improvises schema

  3. 3

    Plan forward-only changes for zero-downtime deploys

Inspect the effective application state before assuming which declaration won.

Synthesis & Production Verification

Production Acceptance Criteria

  • Apply a clean schema from empty via testcontainers
  • Add a column with V2 and confirm idempotent restarts
  • Rename safely with expand-and-contract instead of drop-and-hope

Architectural & Technical Review

Core Interview Questions

Q01Why should ddl-auto=update be avoided in production?Show answer

It cannot reliably handle column renames, lock contention, or index tuning across distributed application replicas.

Q02What happens if a deployed Flyway migration file is modified locally?Show answer

Flyway validates checksums against flyway_schema_history and throws FlywayValidateException at startup.

Q03What should ddl-auto be set to when using Flyway?Show answer

Set spring.jpa.hibernate.ddl-auto=validate so Hibernate confirms entity mappings without mutating the schema.

Production Pitfalls

Critical Anti-Patterns

  • Pitfall: Editing historical migration scripts — Modifying already applied migrations causes checksum validation failures during deployment; always author new forward migrations.
  • Pitfall: Running migrations outside transaction blocks — Non-transactional DDL operations in some databases leave schemas in inconsistent states if a script fails halfway.

Primary Documentation & Specifications