Installation & Setup
About
Liquibase can be installed and configured in several ways depending on our workflow, environment, and integration needs. The setup process generally involves installing Liquibase, connecting to a database, and creating our first changelog.
Installation Methods
1. Command-Line Interface (CLI) Installation
The CLI method is the most direct and environment-agnostic approach.
When to use: Ideal for database administrators, DevOps engineers, or anyone running migrations outside of an application context.
How it works: We download a precompiled Liquibase binary (ZIP/TAR), extract it, and run commands directly from our terminal.
Advantages:
No dependency on a specific programming language or build system.
Can manage any supported database from a single machine.
Easier to integrate into shell scripts and automation jobs.
Disadvantages:
Requires manual updates when new Liquibase versions are released.
Configuration must be managed separately (e.g.,
liquibase.properties
).
Advanced tip: Install Liquibase in a central tools directory and add it to the system
PATH
for global use. For multiple versions, keep them in versioned folders (e.g.,liquibase-4.29.0
) and switch PATH as needed.
2. Maven Plugin Integration
Liquibase has an official Maven plugin, making it easy to run database migrations as part of our Java project’s build lifecycle.
When to use: Ideal for Java developers who want database changes tied directly to the application’s version control and build process.
How it works:
Add the Liquibase Maven plugin to
pom.xml
.Define configuration in Maven profiles or
liquibase.properties
.Run commands like:
mvn liquibase:update mvn liquibase:rollback -Dliquibase.rollbackCount=1
Advantages:
No extra installation — Maven handles dependencies.
Fully integrated with Java build pipelines (e.g., Jenkins, GitLab CI).
Can leverage Maven profiles for environment-specific DB connections.
Disadvantages:
Tied to Maven — not suitable for non-Java projects.
Slightly slower startup due to Maven overhead.
3. Gradle Plugin Integration
Similar to Maven, but designed for Gradle-based builds.
When to use: Ideal for Java/Kotlin projects already using Gradle.
How it works:
Apply the Liquibase Gradle plugin in
build.gradle
orbuild.gradle.kts
.Configure database connection details and changelog paths.
Run commands like:
./gradlew update ./gradlew rollback -PliquibaseCommandValue=1
Advantages:
Easy integration with modern JVM projects.
Can chain Liquibase commands into custom Gradle tasks.
Disadvantages:
Build-system dependent.
4. Spring Boot Auto-Run Integration
Liquibase can run automatically at Spring Boot application startup.
When to use: Ideal for microservices or applications where the database must be in sync at startup without manual intervention.
How it works:
Add the
liquibase-core
dependency to our project.Place changelogs in the classpath.
Spring Boot automatically runs Liquibase on application boot, applying changes before the app fully starts.
Advantages:
Fully automated schema updates.
No manual migration steps in most environments.
Disadvantages:
Risky for production environments if changes are not carefully reviewed.
Startup time increases if migrations are large.
Advanced tip: Use Spring Profiles and Liquibase contexts to limit which changesets run in each environment.
5. Dockerized Liquibase
Liquibase provides an official Docker image.
When to use: Ideal for teams that want reproducible, isolated migration environments without installing Liquibase locally.
How it works:
Pull the image:
docker pull liquibase/liquibase
Run commands inside the container:
docker run --rm -v $(pwd):/liquibase/changelog liquibase/liquibase update \ --url=jdbc:postgresql://db:5432/mydb \ --username=user --password=pass
Advantages:
No host installation needed — everything runs inside a container.
Ensures consistent Liquibase version across team members and CI.
Disadvantages:
Requires Docker installed and accessible.
Slightly more verbose commands unless wrapped in scripts.
6. Direct Java API Usage
Liquibase can be used as a library inside our own Java code.
When to use: For highly customized workflows where migrations are part of complex application logic.
Advantages:
Full control over execution.
Can run migrations programmatically at specific lifecycle points.
Disadvantages:
More setup required.
Tightly couples database migrations with application code.
Database Connection Configuration
Before Liquibase can run migrations, it needs to know where to apply changes meaning it must be able to connect to our target database. This configuration step is essential for both local development and production deployments.
1. Key Connection Parameters
Liquibase requires a few standard parameters to establish a database connection:
url
– The JDBC connection string specifying the database type, host, port, and name.Example for PostgreSQL:
jdbc:postgresql://localhost:5432/mydb
Example for MySQL:
jdbc:mysql://localhost:3306/mydb
username
– The database user with the necessary permissions to run schema changes (CREATE, ALTER, DROP, etc.).password
– The password for the database user.changeLogFile
– The path to the master changelog file (relative or absolute).Optional parameters –
defaultSchemaName
– Default schema to apply changes in (useful for multi-schema DBs).driver
– Fully qualified JDBC driver class (only needed if Liquibase cannot detect it automatically).
2. Configuration Methods
Liquibase supports several ways to provide these parameters, allowing flexibility across environments:
A. Command-Line Arguments We can pass parameters directly in the Liquibase command:
liquibase \
--url=jdbc:postgresql://localhost:5432/mydb \
--username=dbuser \
--password=dbpass \
--changeLogFile=changelog/db.changelog-master.xml \
update
Pros: Fast for testing and one-off commands.
Cons: Not secure for production because passwords may appear in shell history or process lists.
B. liquibase.properties
File
A more secure and maintainable approach is to place parameters in a liquibase.properties
file in our project directory:
url=jdbc:postgresql://localhost:5432/mydb
username=dbuser
password=dbpass
changeLogFile=changelog/db.changelog-master.xml
Then run simply:
liquibase update
Pros: Cleaner commands, reusable across runs.
Cons: Must secure the file if it contains credentials (e.g., use
.gitignore
to avoid committing passwords).
C. Environment Variables Liquibase can read connection parameters from environment variables:
export LIQUIBASE_COMMAND_URL=jdbc:postgresql://localhost:5432/mydb
export LIQUIBASE_COMMAND_USERNAME=dbuser
export LIQUIBASE_COMMAND_PASSWORD=dbpass
liquibase update
Pros: Good for CI/CD pipelines and avoiding credentials in files.
Cons: Still visible to users on the same system via
env
orprintenv
.
D. Build Tool Configuration If using Maven or Gradle, we can define connection settings inside our build configuration, letting us run migrations with:
mvn liquibase:update
# or
./gradlew update
3. Best Practices
Separate environments – Use different connection configs for
dev
,staging
, andprod
(e.g.,liquibase-dev.properties
,liquibase-prod.properties
).Avoid hardcoded passwords – Use environment variables or a secure vault (e.g., HashiCorp Vault, AWS Secrets Manager).
Test before production – Always run
liquibase status
orliquibase updateSQL
before applying changes to production.JDBC drivers – Ensure the required driver
.jar
is on the Liquibase classpath, especially for databases like Oracle or SQL Server.
Change log Organization & Creation
In Liquibase, a changelog is the heart of our database change management process. It’s a file (or a collection of files) that lists changesets - each changeset represents a specific, version-controlled database change.
Properly organizing and creating changelogs is critical for:
Team collaboration
Environment consistency
Rollback reliability
Long-term maintainability of database schema history
1. Changelog File Formats
Liquibase supports multiple formats, letting us choose what fits our workflow:
XML – The most feature-complete and widely used format.
YAML – More human-readable for teams familiar with configuration files.
JSON – Lightweight but less common.
SQL – Ideal when DBAs want raw SQL control.
Example (XML)
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.8.xsd">
<changeSet id="1" author="alice">
<createTable tableName="customer">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="name" type="varchar(255)"/>
</createTable>
</changeSet>
</databaseChangeLog>
2. Master Changelog and Modular Structure
For larger projects, we don’t want a single giant changelog file. Instead, split changes into multiple files and use a master changelog to include them.
Example Structure
db/
changelog/
db.changelog-master.xml
v1/
create-tables.xml
insert-initial-data.xml
v2/
add-orders-table.xml
update-customer-schema.xml
Master Changelog (XML)
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.8.xsd">
<include file="v1/create-tables.xml" relativeToChangelogFile="true"/>
<include file="v1/insert-initial-data.xml" relativeToChangelogFile="true"/>
<include file="v2/add-orders-table.xml" relativeToChangelogFile="true"/>
<include file="v2/update-customer-schema.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
Why use a master changelog ?
Central entry point for Liquibase commands.
Keeps history organized by feature or release.
Makes it easier to add new changes without modifying old files.
3. Writing a Good Changeset
A changeset is the atomic unit of Liquibase changes. It has three required attributes
id
– A unique identifier within the author’s namespace.author
– The person or system that created it.changes
– One or more operations (e.g., create table, insert data).
Best Practices for Changesets
Unique IDs: Never reuse an
id
with the sameauthor
.Small & Focused: Each changeset should do one logical change (e.g., create a table, add a column, insert reference data).
Rollback Ready: Always include rollback instructions for production safety.
Immutable History: Never modify an already-applied changeset; create a new one for fixes.
4. Rollback in Changelogs
Defining rollback steps allows us to reverse changes if something goes wrong. Example
<changeSet id="2" author="bob">
<addColumn tableName="customer">
<column name="email" type="varchar(255)"/>
</addColumn>
<rollback>
<dropColumn tableName="customer" columnName="email"/>
</rollback>
</changeSet>
5. Organizing by Context and Labels
Liquibase allows us to tag changesets for conditional execution:
Contexts – Group changes by environment (e.g.,
dev
,test
,prod
).Labels – Tag changes for feature-specific deployments.
Example with Contexts
<changeSet id="3" author="carol" context="dev">
<insert tableName="sample_data">
<column name="id" valueNumeric="1"/>
<column name="name" value="Test User"/>
</insert>
</changeSet>
Run only dev
context
liquibase --contexts=dev update
6. Changelog Location & Version Control
Store changelogs in source control alongside application code.
Keep them in a dedicated
db/changelog
directory.Use branching and pull requests to review schema changes just like code.
Last updated