Quick Answer:
PostgreSQL does not allow CREATE DATABASE inside a transaction. Liquibase wraps changes in transactions by default, which causes this error. You can either:
Create the database outside Liquibase (safest), or
Use a Liquibase changeset with
runInTransaction="false"to runCREATE DATABASEwithout a transaction.
Applies to
- Liquibase Secure (Pro)
- Liquibase Community (Open Source)
Conditions
- Applies to all supported PostgreSQL versions
- Attempting to create a new database using Liquibase (
CREATE DATABASE)
Symptoms
Running Liquibase against PostgreSQL to create a new database fails immediately, even though the same approach may succeed in other databases, such as CockroachDB.
Error Message
liquibase.exception.DatabaseException: ERROR: CREATE DATABASE cannot run inside a transaction block
[Failed SQL: (0) CREATE DATABASE test]
Root Cause
PostgreSQL behavior: PostgreSQL does not allow
CREATE DATABASE(and certain other commands likeVACUUM,REINDEX,CREATE TABLESPACE) inside a transaction block.Liquibase behavior: Liquibase executes most changes inside transactions for consistency and rollback safety.
CockroachDB difference: CockroachDB, though it uses the PostgreSQL JDBC driver, has different semantics. It allows
CREATE DATABASEwithin transactions, which is why behavior differs.
Resolution
Option 1 (Recommended, safest): Create the database outside Liquibase
-
Create the database manually
Use a PostgreSQL client or admin tool (e.g.,psql):CREATE DATABASE test;
-
Update Liquibase configuration
Point Liquibase to the newly created database (test) in your JDBC connection URL:jdbc:postgresql://localhost:5432/test
Run Liquibase migrations
Once connected to the new database, run Liquibase to apply schema changes as usual.
Option 2 (Alternative): Use runInTransaction="false" in Liquibase
Liquibase supports a runInTransaction changeset attribute. Setting this to false prevents Liquibase from wrapping the statement in a transaction, allowing CREATE DATABASE to succeed.
Example changeset in formatted SQL:
--liquibase formatted sql
--changeset your.name:1 runInTransaction:false
CREATE DATABASE test;Or in XML:
<changeSet id="1" author="your.name" runInTransaction="false">
<sql>CREATE DATABASE test;</sql>
</changeSet>⚠️ Warning:
If
runInTransactionis set tofalseand an error occurs part way through running a changeset that contains multiple statements, theDATABASECHANGELOGtable may end up in an invalid or inconsistent state.Use this option only when you understand the risks and need Liquibase to handle database creation as part of your workflow.
For details, see Liquibase Documentation: runInTransaction.
Notes
This is expected PostgreSQL behavior and not a Liquibase bug.
Other databases, like CockroachDB, have the ability to run
CREATE DATABASEin transactions, which is not portable to PostgreSQL. Scripts written for CockroachDB may require modification when run against PostgreSQL.
Best Practices
For automation, handle database creation in provisioning scripts (e.g., Terraform, Ansible, bash +
psql) before running Liquibase migrations.Keep Liquibase responsible for schema changes, not database provisioning—unless you are intentionally using the
runInTransaction="false"workaround.
Comments
0 comments
Article is closed for comments.