Create custom rollback statements in Liquibase
Last updated: July 14, 2025
Procedure
Decide if you need to create rollback statements.
Liquibase can automatically generate rollback SQL for many Change Types, such as createTable
, renameColumn
, and addColumn
. If your changelog only uses these supported Change Types, you do not need to manually define rollback logic—Liquibase will handle it for you when you run the rollback
command.
However, not all Change Types support automatic rollback. For example, dropTable
, insert
, and all formatted SQL changesets do not have a clearly defined inverse operation, so Liquibase cannot generate rollback SQL for them. In these cases, you must provide custom rollback logic inside the changeset.
Note: When rolling back stored logic, Liquibase does not restore the previously stored version. Instead, Liquibase rolls back to the exact file/code specified in the custom rollback.
You can also override the default rollback even for Change Types that do support auto rollback, giving you more control over how your database is restored.
You can use automatic rollback with XML, JSON, and YAML changelogs for any Change Type marked as "Supported" in What change types can I use auto rollback with?
Add a rollback statement.
For any change that you'd like to add rollback to, add a <rollback>
tag inside the <changeSet>
tag.
--changeset liquibase-user:1
DROP PROCEDURE hello_world;
--rollbackSqlFile path:release_1.0/rollback_45895.sql
databaseChangeLog:
- changeSet:
id: 2
author: liquibaseuser
changes:
- dropTable:
tableName: person
rollback:
createTable:
catalogName: cat
columns:
- column: null
name: address
type: varchar(255)
remarks: A String
schemaName: public
tableName: person
{
"databaseChangeLog": [
{
"changeSet": {
"id": "2",
"author": "liquibaseuser",
"changes": [
{
"dropTable": {
"tableName": "person"
}
}
],
"rollback": [
{
"createTable": {
"catalogName": "cat",
"columns": [
{
"column": {
"name": "address",
"type": "varchar(255)"
}
}
],
"remarks": "A String",
"schemaName": "public",
"tableName": "person"
}
}
]
}
}
]
}
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
http://www.liquibase.org/xml/ns/pro
http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
<changeSet author="liquibaseuser" id="2">
<dropTable tableName="person"/>
<rollback>
<createTable catalogName="department"
remarks="A String"
schemaName="public"
tableName="person"
<column name="address" type="varchar(255)"/>
</createTable>
</rollback>
</changeSet>
</databaseChangeLog>
If you prefer to store rollback logic in a separate file, use the rollbackSqlFile
tag.
Note: You can include options like custom delimiters in the rollbackSqlFile
tag.
--changeset liquibase-user:1
DROP PROCEDURE hello_world;
--rollbackSqlFile path:release_1.0/rollback_45895.sql
Add additional rollback statements.
You can also specify multiple Change types within a single <rollback>
statement or across multiple <rollback>
statements
- changeSet:
id: multiRollbackTest
author: liquibaseuser
changes:
- createTable:
tableName: multiRollback1
columns:
- column:
name: id
- createTable:
tableName: multiRollback2
columns:
- column:
name: id
- createTable:
tableName: multiRollback3
columns:
- column:
name: id
rollback:
- dropTable:
tableName: multiRollback1
- dropTable:
tableName: multiRollback2
rollback:
- dropTable:
tableName: multiRollback3
{
"changeSet": {
"id": multiRollbackTest,
"author": "liquibaseuser",
"changes": [
{
"createTable": {
"tableName": "multiRollback1",
"columns": [
{
"column": {
"name": "id"
}
}
]
},
"createTable": {
"tableName": "multiRollback2"
"columns": [
{
"column": {
"name": "id"
}
}
]
},
"createTable": {
"tableName": "multiRollback3"
"columns": [
{
"column": {
"name": "id"
}
}
]
}
}
],
"rollback": [
{
"dropTable": {
"tableName": "multiRollback1"
},
"dropTable": {
"tableName": "multiRollback2"
}
}
],
"rollback": [
{
"dropTable": {
"tableName": "multiRollback3"
}
}
],
}
}
Change Type syntax
<changeSet id="multiRollbackTest" author="liquibaseuser">
<createTable tableName="multiRollback1">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback2">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback3">
<column name="id" type="int"/>
</createTable>
<rollback>
<dropTable tableName="multiRollback1"/>
<dropTable tableName="multiRollback2"/>
</rollback>
<rollback>
<dropTable tableName="multiRollback3"/>
</rollback>
</changeSet>
Raw SQL
<changeSet id="multiRollbackTest" author="liquibaseuser">
<createTable tableName="multiRollback1">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback2">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback3">
<column name="id" type="int"/>
</createTable>
<rollback>
drop table multiRollback1;
drop table multiRollback2;
</rollback>
<rollback>drop table multiRollback3</rollback>
</changeSet>