Drift Report

Liquibase displays a drift report of a user's source and target database.

The drift report is a Liquibase operation report that informs you of database drift.

Database drift occurs when changes to one database are not made to others – often when manual changes are made outside of automation. These inconsistencies are challenging to detect. Once detected, tracking down the problem is manual, frustrating, and takes time.

If you're working in an environment that experiences database drift, Liquibase drift reports can alert you of the drift and show you the changes that need to be addressed. This simplifies the process and minimizes the amount of time databases are out of sync.

In Liquibase 4.25.0 and later, you can automatically generate a database drift report using the Liquibase diff command. The drift report shows the differences between two live databases or between a database and a snapshot from a previous point in time. Adding this check to your CI/CD pipeline gives you ongoing visibility into database drift while maintaining the speed and reliability of CI/CD automation.

In 4.25.1 and later, you can also generate a drift report with the diff-changelog command.

It is a best practice to explicitly set a drift severity level to match your team's expectation of allowable drift.

Uses

Using Liquibase drift detection can help developers, DBAs, DevOps engineers, and managers in the following ways:

  • Easily scan and understand differences with summary of differences section
  • Quickly identify and remediate differences with highlighted object differences
  • Collaborate with your team to troubleshoot differences with new shareable report

Enable operation reports

To enable all operation reports, you must:

  1. Set the --license-key property using your Liquibase Pro license key.
  2. Choose how often to generate reports. You can either:
    • Always generate reports:
    • Selectively generate reports at runtime:
      • Command line: liquibase --reports-enabled=true diff
      • JVM system property: JAVA_OPTS="-Dliquibase.reports.enabled=true" liquibase diff

Drift reports in automation

To automatically use Liquibase drift reports in your CI/CD pipeline, follow these steps in your CI/CD tool:

  1. Create a LiquibaseDatabaseSnapshot job that runs the Liquibase snapshot command. This stores the current state of your database. It is a best practice to store your database snapshot in an artifact repository like Artifactory, Sonatype Nexus Repository, Amazon S3, Azure Blob Storage, or a database-specific artifact repository.
  2. Configure your snapshot job to run at your desired frequency, such as once per release.
  3. Repeat Steps 1–2 for every database whose state you want to track with Liquibase drift reports.
  4. Create a LiquibaseDriftReport job that compares the snapshot to the current database state or another snapshot. This job must:
    1. Enable the drift report with --reports-enabled (global scope) or --report-enabled (command scope).
    2. Run the Liquibase diff or diff-changelog command against your desired databases.
    3. (Optional) Specify the --drift-severity-* parameters to control whether Liquibase should respond differently to changed, missing, or unexpected content.
  5. Tip: For more information, see the Examples section of this page.

  6. Configure your drift report job to run at your desired frequency, such as once per day.

Examples

Setting parameters

You can modify the drift report output with the parameters listed in the tables on this page. In the CLI, global parameters go to the left of the command and command parameters go to the right of the command.

liquibase \
    --reports-enabled=true \
    --reports-path=reports \
    --reports-name=06.diff_report.html \
  diff \
    --drift-severity=4 \
    --reference-url="offline:sqlserver?snapshot=mySnapshot.json"

Note: For readability, this page shows parameters on new lines. If you type in the commands on a single line, do not include the backslashes \ shown in the examples.

You can also set parameters in your liquibase.properties file, as environment variables, or in a flow file. For a list of parameters and their syntax in each format, see the Global parameters and Command parameters sections of this page.

Disable reports by default; enable only the drift report

If you want to keep reports disabled by default and enable only the drift report, you can use the command parameter --report-enabled (singular) on the diff and diff-changelog commands. For example:

liquibase diff \
    --report-enabled=true \
    --report-name=my_drift_report.html

This is an example flow file running a drift report:

stages:
  Drift_Detection:
    actions:
      - type: liquibase
        command: diff
        cmdArgs: { referenceUrl: "offline:sqlserver?snapshot=mySnapshot.json",
                        drift-severity: 1,
                        drift-severity-missing: 2,
                        drift-severity-unexpected: 3,
                        drift-severity-changed: 4}
        globalArgs: { mirror-console-messages-to-log: "true",
                        reports-enabled: "true",
                        reports-path: "reports",
                        reports-name: "drift-report.html"}

Note: This example uses reports-enabled (plural) within globalArgs to enables all operation reports. To enable this specific kind of report, but not other reports, you must instead set report-enabled (singular) in cmdArgs.

Halt deployment if any drift is detected

liquibase
    --reports-enabled=true
  diff
    --drift-severity=4

Log missing or unexpected objects, but ignore changed objects

liquibase
    --reports-enabled=true
  diff
    --drift-severity-changed=0
    --drift-severity-missing=2
    --drift-severity-unexpected=2

Another way to specify this is to explicitly set --drift-severity-missing and --drift-severity-unexpected to 2 and not specify a value for --drift-severity-changed, so it remains at its default value of 0.

liquibase
    --reports-enabled=true
  diff
    --drift-severity-missing=2
    --drift-severity-unexpected=2

A third way to specify this is by setting --drift-severity to 2 as a default for all drift and then overriding it only for changed objects:

liquibase
    --reports-enabled=true
  diff
    --drift-severity=2
    --drift-severity-changed=0

Global parameters

Use these parameters to control the behavior of all operation reports.

Note: Syntax for each parameter is specified in kebab-case (CLI and flow file), camelCase (properties file and JAVA_OPTS), and MACRO_CASE (environment variable).

Syntax (--cli, {flow-file}, propertiesFile, ENV_VAR) Type Description Requirement
--reports-enabled
globalArgs: {reports-enabled: "val"}
liquibase.reports.enabled
LIQUIBASE_REPORTS_ENABLED
Boolean Enables or disables all reports at the global level. Overridden by --report-enabled at the command level. Default: false. Required (either this or --report-enabled)
--reports-name
globalArgs: {reports-name: "val"}
liquibase.reports.name
LIQUIBASE_REPORTS_NAME
String Specifies the name of the report file at the global level. Overridden by --report-name at the command level. By default, Liquibase generates a new report file labeled with a timestamp (user's local time). If you set a custom name, Liquibase overwrites the existing file every time you generate a new report. Default: report-<DD-Mon-YYYY-HHmmss>.html. Optional
--reports-path
globalArgs: {reports-path: "val"}
liquibase.reports.path
LIQUIBASE_REPORTS_PATH
String Specifies the file path to the report file at the global level. Overridden by --report-path at the command level. Default: ./. Optional

Command parameters

Use these command parameters if you want to specify operation report behavior for a specific command.

When Liquibase detects database drift, it records that in your drift report. Use the --drift-severity parameter to specify a severity return code (severity level) for all kinds of drift: changed, missing, or unexpected content. The severity return code you set tells Liquibase how to react when it detects drift. You can use the severity return code as an alert for the rest of your CI/CD pipeline.

  • BLOCKER (4): drift is a blocker (most severe)
  • CRITICAL (3): drift is a critical error
  • MAJOR (2): drift is a major failure
  • MINOR (1): drift is a minor failure
  • INFO (0): drift is treated as an informational message (least severe)

If you want Liquibase to react to changed, missing, or unexpected content in different ways, you can set the individual --drift-severity-* parameters to specify a severity return code for each particular kind of drift. These parameters take priority over --drift-severity.

Syntax (--cli, {flow-file}, propertiesFile, ENV_VAR) Type Description Requirement
--report-enabled
cmdArgs: {report-enabled: "val"}
liquibase.command.<cmdName>.reportEnabled
LIQUIBASE_COMMAND_<CMDNAME>_REPORT_ENABLED
Boolean

Enables a report at the command level. Overrides the global argument --reports-enabled. Default: false.

Required (either this or --reports-enabled)
--drift-severity
cmdArgs: {drift-severity: "val"}
liquibase.command.<cmdName>.driftSeverity
LIQUIBASE_COMMAND_<CMDNAME>_DRIFT_SEVERITY
String

Specifies the severity level of all error types in the drift report (changed, missing, or unexpected content). Valid values are INFO (0), MINOR (1), MAJOR (2), CRITICAL (3), and BLOCKER (4), from least severe to most severe. If both --drift-severity and one of the individual error type arguments are set, the individual error type arguments take priority. Default: INFO.

Optional
--drift-severity-changed
cmdArgs: {drift-severity-changed: "val"}
liquibase.command.<cmdName>.driftSeverityChanged
LIQUIBASE_COMMAND_<CMDNAME>_DRIFT_SEVERITY_CHANGED
String

Specifies the severity level of changed content in the drift report. Valid values are INFO (0), MINOR (1), MAJOR (2), CRITICAL (3), and BLOCKER (4), from least severe to most severe. Overrides the value of --drift-severity for changed content only. Default: INFO.

Optional
--drift-severity-missing
cmdArgs: {drift-severity-missing: "val"}
liquibase.command.<cmdName>.driftSeverityMissing
LIQUIBASE_COMMAND_<CMDNAME>_DRIFT_SEVERITY_MISSING
String

Specifies the severity level of missing content in the drift report. Valid values are INFO (0), MINOR (1), MAJOR (2), CRITICAL (3), and BLOCKER (4), from least severe to most severe. Overrides the value of --drift-severity for missing content only. Default: INFO.

Optional
--drift-severity-unexpected
cmdArgs: {drift-severity-unexpected: "val"}
liquibase.command.<cmdName>.driftSeverityUnexpected
LIQUIBASE_COMMAND_<CMDNAME>_DRIFT_SEVERITY_UNEXPECTED
String

Specifies the severity level of unexpected content in the drift report. Valid values are INFO (0), MINOR (1), MAJOR (2), CRITICAL (3), and BLOCKER (4), from least severe to most severe. Overrides the value of --drift-severity for unexpected content only. Default: INFO.

Optional
--open-report
cmdArgs: {open-report: "val"}
liquibase.command.<cmdName>.openReport
LIQUIBASE_COMMAND_<CMDNAME>_OPEN_REPORT
Boolean

If true, automatically opens the report in your default browser. Default: false.

Optional
--report-name
cmdArgs: {report-name: "val"}
liquibase.command.<cmdName>.reportName
LIQUIBASE_COMMAND_<CMDNAME>_REPORT_NAME
String

Specifies the name of the report file at the command level. Overrides the global argument --reports-name. By default, Liquibase generates a new report file labeled with a timestamp (user's local time). If you set a custom name, Liquibase overwrites the existing file every time you generate a new report. Default: report-<DD-Mon-YYYY-HHmmss>.html.

Optional
--report-path
cmdArgs: {report-path: "val"}
liquibase.command.<cmdName>.reportPath
LIQUIBASE_COMMAND_<CMDNAME>_REPORT_PATH
String

Specifies the file path to the report file at the command level. Overrides the global argument --reports-path. Default: ./.

Optional

Troubleshooting

If you experience performance issues while generating drift reports, such as an OutOfMemoryError exception, see the solutions described on Memory Limits of Inspecting Large Schemas.