How to divide Liquibase package structure for dev and prod environment in Spring Boot?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Liquibase works best in Spring Boot when the changelog structure reflects the deployment policy instead of mixing every environment concern into one file tree. The usual goal is to keep schema changes shared across environments, while isolating environment-specific data loads, test helpers, and optional features so development and production can evolve safely.
Keep One Shared Schema History
The first design rule is that database schema history should usually be shared, not duplicated. Development and production should not have different versions of the same core table definition unless you are intentionally running different applications.
A simple structure looks like this:
The common directory holds schema changes that belong everywhere. The environment directories hold changes that are explicitly environment-specific.
That keeps the main evolution path easy to reason about and avoids the trap of having two unrelated changelog trees that drift apart.
Use One Master Changelog With Includes
The usual pattern is to keep one master changelog and include shared files first.
Then include environment-specific files only when their context should apply.
This approach keeps the dependency order explicit and makes it much easier to audit what runs in each environment.
Use Contexts for Environment-Specific Changes
Liquibase contexts are the cleanest way to tag changesets that should run only in selected environments.
In Spring Boot, activate the right context through configuration.
and for production:
This is much safer than maintaining two different master changelogs that duplicate most of the same history.
Separate Schema From Data Seeding
A common source of chaos is putting development seed data next to structural schema changes without any clear boundary. A better rule is:
- schema lives in shared changelogs
- test and demo data lives in context-gated changelogs
- one-off production backfills are isolated and clearly named
That separation matters because production migrations should be boring and predictable. Development conveniences such as sample users or fake reference data should not even be eligible to run there.
Use Spring Profiles to Select Liquibase Settings
Spring Boot profiles are a natural way to keep the Liquibase configuration aligned with the application environment.
This avoids hardcoding the environment choice inside the changelog itself and keeps deployment behavior visible in the Spring configuration that already controls the environment.
Common Pitfalls
The biggest mistake is splitting the schema history completely into separate dev and prod trees. That usually leads to divergence, duplication, and confusion about which changes are the real history of the database.
Another issue is using environment-specific directories without contexts or labels, then assuming the right files will somehow be skipped automatically.
Teams also often mix test data, schema changes, and one-time operational fixes in one flat folder with no naming convention. That makes production review harder than it needs to be.
Finally, do not use Liquibase package structure as a substitute for deployment discipline. The file layout helps, but the real safety comes from shared schema history plus explicit environment gating.
Summary
- Keep one shared schema history for changes that belong in every environment.
- Use separate directories only for clearly environment-specific changes such as seed data or prod-only backfills.
- Drive environment selection with Liquibase contexts and Spring profiles.
- Avoid duplicating dev and prod master changelogs when most schema history is the same.
- Separate schema evolution from data seeding so production migrations stay predictable.

