✅ Short Answer
Preconditions in Liquibase are conditions that must be true before a changeset or changelog is applied.
If the precondition fails, Liquibase can be told to halt, warn, or continue, depending on your configuration.
🔎 Detailed Explanation
A precondition acts like a safeguard — for example:
- “Only run this change if a table exists”
- “Skip this if a column is already present”
- “Apply this only on PostgreSQL”
You can define preconditions:
- At the changelog level (applies to all changesets)
- At the changeset level (applies to one changeset only)
✅ Common Use Cases for Preconditions
| Use Case | Precondition Type |
|---|---|
| Ensure a table exists | tableExists |
| Ensure a column doesn’t already exist | not, columnExists |
| Restrict to a DBMS (e.g., PostgreSQL) | dbms |
| Block updates on production | runningAs (based on user) |
🧪 Example – XML format
<changeSet id="1" author="alice">
<preConditions onFail="HALT">
<not>
<tableExists tableName="users"/>
</not>
</preConditions>
<createTable tableName="users">
<column name="id" type="int" autoIncrement="true"/>
<column name="username" type="varchar(255)"/>
</createTable>
</changeSet>
✅ This change will only run if the users table does not exist.
If the table does exist, Liquibase will halt the migration (because onFail="HALT").
🛠️ Other Precondition Types
sqlCheck– Run custom SQL that returnstrue/falsechangeLogPropertyDefinedcolumnExistssequenceExistsforeignKeyConstraintExistscustomPrecondition– write your own in Java
📌 Key Takeaways
✅ Preconditions let you add logic before a changeset runs, preventing errors or unintended changes.
✅ You can halt, warn, or skip based on the result.
✅ They are useful for idempotency, environment targeting, and fail-safety.