Flyway
database migration
schema history
baseline
error resolution

Flyway Found non-empty schemas public without schema history table Use baseline - on Empty database

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

This Flyway message means the schema already contains objects, but Flyway cannot find its schema history table, so it has no idea which migrations have been applied. The fix is usually to baseline the existing database intentionally, not to force Flyway to pretend it is starting from a brand-new empty schema.

What The Message Actually Means

When Flyway sees a non-empty schema such as public and no flyway_schema_history table, it treats the database as an existing unmanaged schema. That is a safety check.

Without a baseline, Flyway cannot tell whether:

  • the schema was created manually
  • migrations were run by some other tool
  • migrations already exist but were never recorded by Flyway

If Flyway simply started executing versioned migrations from V1, it could recreate tables that already exist or apply the same structural changes twice.

What Baseline Does

Baselining tells Flyway, "assume this database already starts at version X." Flyway records that version in the schema history table without replaying the earlier migration chain against the existing objects.

That is the correct move when you adopt Flyway for a database that already contains production schema objects.

A direct baseline command looks like this:

bash
1flyway -url=jdbc:postgresql://localhost:5432/app \
2       -user=appuser \
3       -password=secret \
4       -baselineVersion=1 \
5       baseline

After that, Flyway creates its schema history table and records the baseline version. Future migrations then start above that version.

baselineOnMigrate Versus Explicit baseline

Flyway also supports baselineOnMigrate=true. With that setting, Flyway can baseline automatically when migrate runs against a non-empty schema that lacks a schema history table.

Example configuration:

properties
1flyway.url=jdbc:postgresql://localhost:5432/app
2flyway.user=appuser
3flyway.password=secret
4flyway.baselineOnMigrate=true
5flyway.baselineVersion=1

This is convenient for controlled adoption, but it removes an explicit safety step. In production environments, many teams prefer an intentional one-time baseline command because it makes the transition visible and reviewable.

Why The Title Often Mentions An "Empty Database"

The wording around this problem is confusing because people often say, "but my database is empty." In practice, Flyway cares about whether the configured schema is empty, not whether the entire server or catalog feels empty to you.

For example, on PostgreSQL, the public schema may already contain tables, extensions, or other objects. That is enough for Flyway to classify it as non-empty.

So the message is not contradicted by your intuition. It is using Flyway's schema-level view of emptiness.

Choosing The Right Baseline Version

The baseline version should represent the state the database is already in. If the existing schema corresponds to what your codebase thinks of as migration V5, then baselining at 1 would be misleading.

A common strategy is:

  1. inspect the existing schema
  2. decide which migration version best represents that state
  3. baseline at that version
  4. keep later migrations versioned above it

If you are adopting Flyway midstream, you may also create a snapshot-style baseline migration script that represents the existing schema cleanly and then start new incremental migrations after that point.

A Safe Adoption Workflow

For an existing database, a reasonable workflow is:

  1. back up the database
  2. inspect the current schema and objects
  3. decide the correct baseline version
  4. run flyway baseline
  5. verify flyway info
  6. run future migrations normally

That verification step matters. flyway info should show the baseline entry in the schema history table before you proceed.

bash
flyway info

Do Not Baseline Casually

Baselining is not a magic error suppressor. If you baseline the wrong database or wrong version, Flyway will happily build future history on top of a false starting point.

That can be worse than the original error because it hides the mismatch until a later migration fails in a harder-to-repair way.

If the schema should truly be empty, the better fix may be to clean or recreate the schema instead of baselining it.

Example: Spring Boot Configuration

If Flyway runs through Spring Boot, the same idea applies through application properties.

properties
1spring.flyway.enabled=true
2spring.flyway.locations=classpath:db/migration
3spring.flyway.baseline-on-migrate=true
4spring.flyway.baseline-version=1

Use this only when you deliberately want startup-time baselining for an existing schema. It should not be enabled casually across every environment without understanding the consequence.

Common Pitfalls

  • Treating the error as something to silence instead of a warning about unknown schema state.
  • Using baselineOnMigrate=true everywhere without confirming the current database version first.
  • Confusing an empty database server with an empty target schema.
  • Choosing an arbitrary baseline version that does not match the existing schema state.
  • Forgetting to verify the new schema history table with flyway info after baselining.

Summary

  • The error means the target schema already has objects, but Flyway has no schema history table.
  • The usual fix is to baseline the existing schema intentionally.
  • 'baselineOnMigrate can automate that, but explicit baseline is often safer.'
  • Pick a baseline version that matches the real current schema state.
  • If the schema truly should be empty, cleaning or recreating it may be better than baselining.

Course illustration
Course illustration

All Rights Reserved.