Quick verdict
Choose Alembic if your application is written in Python and defines its tables with SQLAlchemy: it reads your models, drafts migrations with --autogenerate, gives every revision an upgrade() and downgrade(), and is MIT licensed. Choose Liquibase if database changes must be managed independently of one application, for example by a platform or DBA team, across several engines, or with change definitions in XML, YAML, JSON or SQL that non-Python teams can read. Remember that Liquibase Community 5.0 and later uses the FSL-1.1-ALv2 licence, and its governance features (drift detection, policy checks, targeted rollback) are in the paid Liquibase Secure.
Liquibase is a database change management tool from Liquibase Inc. You write changesets, each with an id and author, in a changelog file in SQL, XML, YAML or JSON, and Liquibase records deployed changesets in its DATABASECHANGELOG table. It runs on Java (17 or later from version 5.0) from the command line, Docker, Maven, Gradle or Spring Boot. Liquibase Community 5.0.4 (20 August 2026) is the latest release on GitHub; the commercial edition is Liquibase Secure.
Alembic is "a database migrations tool written by the author of SQLAlchemy", in the words of its PyPI page. Migrations are Python files called revisions, each with an upgrade() and a downgrade() function that call operations such as op.create_table(). Alembic records the current revision in an alembic_version table. Version 1.20.0 was released on 11 September 2026; it requires Python 3.10 or later and is MIT licensed.
Both tools apply the same kinds of DDL commands; the difference is who writes the change definitions, in which language, and how tightly they are tied to the application code. For a comparison with a SQL-first tool, see Flyway vs Alembic.
Side by side
| Aspect | Liquibase | Alembic |
|---|---|---|
| Change format | Changesets in SQL, XML, YAML or JSON changelogs | Python revision files with upgrade() and downgrade() |
| Tied to an application framework | No; independent of the application language | Yes, built on SQLAlchemy (Core and ORM) |
| Generating changes | diff-changelog compares two databases; generate-changelog captures an existing one |
--autogenerate compares SQLAlchemy model metadata with the database |
| Rollback (free) | rollback to a tag, by count or by date; automatic for many modelled change types |
alembic downgrade runs the downgrade() functions you (or autogenerate) wrote |
| History model | Ordered changelog; changesets identified by id, author and file | Directed acyclic graph of revisions, with branches and alembic merge |
| Supported databases | 65+ databases, including NoSQL platforms through extensions | SQLAlchemy dialects: PostgreSQL, MySQL and MariaDB, SQLite, Oracle, SQL Server built in, plus external dialects |
| Runtime | Java 17 or later | Python 3.10 or later |
| Licence | Community 5.0+: FSL-1.1-ALv2 (each release converts to Apache 2.0 after two years) | MIT |
| Paid edition | Liquibase Secure (drift detection, policy checks, targeted rollback) | None |
| Main trade-off | Separate tool and runtime to adopt, but independent of the application stack | Very convenient in a SQLAlchemy app, but of little use outside Python |
Key differences
Changelogs versus Python revisions
A Liquibase change is data, not code. This YAML changeset is based on the createTable example in the Liquibase documentation:
# Liquibase YAML changelog
databaseChangeLog:
- changeSet:
id: createTable-example
author: liquibase-docs
changes:
- createTable:
tableName: person
columns:
- column:
name: address
type: varchar(255)An Alembic change is a Python module. This is the revision from the Alembic tutorial, after the developer filled in the generated template:
# Alembic revision (Python), e.g. alembic/versions/1975ea83b712_create_account_table.py
revision = '1975ea83b712'
down_revision = None
branch_labels = None
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table(
'account',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('name', sa.String(50), nullable=False),
sa.Column('description', sa.Unicode(200)),
)
def downgrade():
op.drop_table('account')Because Alembic revisions are Python, you can use loops, conditionals and the SQLAlchemy expression language, and data migrations can reuse application code. Because Liquibase changesets are declarative, they can be read and reviewed by people who do not write Python, and the same XML, YAML or JSON change can be deployed to different engines. In our view this is the deciding question: is the schema owned by one Python application, or shared?
Autogenerate versus diff: generating migrations and their limits
Alembic's alembic revision --autogenerate compares your SQLAlchemy MetaData with the live database and writes a candidate revision. The Alembic documentation lists what it detects: tables and columns added or removed, nullability changes, basic changes to indexes and explicitly named unique constraints, and basic foreign key changes. Column type comparison is controlled by the compare_type setting and reliably detects major changes, such as Numeric to String, and server default comparison must be switched on with compare_server_default. The documentation is explicit about what autogenerate cannot detect: table and column renames (they appear as a drop and an add), anonymous (unnamed) constraints, some special types such as Enum on backends that do not support it, standalone sequences, and some constraint types such as PRIMARY KEY and EXCLUDE. It says autogenerate "is not intended to be perfect" and that you must review and correct the candidate migrations.
Liquibase does not read application models. Its Community edition offers diff, which reports differences between two databases, diff-changelog, which writes a changelog of changesets to reconcile them, and generate-changelog, which captures the current state of a database as a changelog, typically when adopting Liquibase on an existing system. The usual workflow is to write changesets by hand and use the diff commands as a check or a starting point.
The rename problem deserves a specific warning: if Alembic autogenerate sees a renamed column as a dropped column plus a new one, applying that revision unchanged would lose the column's data. Replace the generated drop and add with op.alter_column(..., new_column_name=...) before you run it.
Rollback and branching
Every Alembic revision has a downgrade() function, and alembic downgrade -1 or alembic downgrade <revision> runs them in reverse. Rollback is free and only as good as the downgrade code. Alembic treats revisions as a directed acyclic graph: when two developers create revisions from the same parent, you get two heads, and alembic merge creates a merge revision that joins them. Alembic can also write SQL instead of running it (offline mode, with --sql), so a DBA can review or apply the script.
Liquibase Community includes rollback to a tag, rollback-count and rollback-to-date, each with a -sql preview. Many modelled change types have automatic rollback; formatted SQL changesets need explicit -- rollback statements. Rolling back a single changeset out of order (rollback-one-changeset) or a single deployment (rollback-one-update) requires Liquibase Secure. Liquibase's ordering is the order of changesets in the changelog rather than a revision graph, and it offers contexts, labels and preconditions to control which changesets run where.
Databases and SQLite
Alembic supports the databases SQLAlchemy supports. SQLAlchemy includes dialects for PostgreSQL, MySQL and MariaDB, SQLite, Oracle and Microsoft SQL Server, and the project lists external dialects for others such as Snowflake, BigQuery, Redshift, Databricks and CockroachDB, each needing a DBAPI driver. SQLite gets special handling: because SQLite has limited ALTER TABLE support, Alembic offers "batch" migrations that create a new table with the desired structure, copy the data with INSERT ... SELECT, drop the old table and rename the new one. For the engine choice itself, see SQLite vs PostgreSQL.
Liquibase lists support for more than 65 databases, including relational engines, cloud data platforms such as Snowflake, BigQuery and Databricks, and NoSQL platforms such as MongoDB and Cassandra, many through extensions. From version 5.0, drivers and extensions are installed with the built-in package manager (liquibase lpm) rather than bundled.
Licence and commercial support
Alembic is MIT licensed and maintained in the SQLAlchemy organisation on GitHub. There is no paid edition.
Liquibase Community moved to the Functional Source License (FSL-1.1-ALv2) with version 5.0 on 30 September 2025. Liquibase says you can still use it in production and modify it, but third parties may not commercialise it in a way that competes with Liquibase; each release converts to Apache 2.0 after two years, and 4.x releases stay Apache 2.0. FSL is not an OSI-approved open source licence. Liquibase Secure adds drift detection, policy checks, targeted rollback, flow files, compliance reporting, secrets-manager integration and SLA-backed support.
Pricing and licensing
Alembic is free and open source under the MIT licence. There is no commercial edition.
Liquibase Community is free to use under FSL-1.1-ALv2. Liquibase Secure is sold in Starter, Team, Business and Enterprise plans; no prices were published on liquibase.com/pricing in October 2026, every plan requires a Professional Services package, and Starter is limited to companies with under USD 1 billion in annual revenue.
Pricing checked on the vendors' official pages on 7 October 2026. Prices change; confirm before buying.
Where each one leads
Liquibase strengths
- Independent of the application language, so several applications and teams can share one change process
- Changelogs in SQL, XML, YAML or JSON that non-developers can review
- Database-independent change types and automatic rollback for many of them
- Rollback by tag, count and date, plus diff and changelog generation, in the free edition
- Supports 65+ databases, including NoSQL platforms through extensions
Alembic strengths
- Generates candidate migrations from SQLAlchemy models with --autogenerate
- Revisions are Python, so migrations can use application code and conditional logic
- Every revision has an upgrade() and downgrade(); no paid tier for rollback
- Branching and merge revisions for parallel development
- MIT licence, and batch mode for SQLite's limited ALTER TABLE support
Limitations
Liquibase limitations
- Needs a Java 17+ runtime and a separate tool chain alongside a Python application
- Does not read ORM models; changesets are written by hand or generated from database diffs
- Community 5.0+ licence is FSL-1.1-ALv2 rather than an OSI-approved open source licence
- Targeted rollback, drift detection and policy checks need Liquibase Secure, with no public prices
Alembic limitations
- Tied to SQLAlchemy and Python; of little use to teams on other stacks
- Autogenerate misses renames, anonymous constraints, standalone sequences and some types, so every candidate needs review
- Downgrades are only as reliable as the code you write for them
- No built-in drift detection, policy checks or deployment reports
When to choose each
Choose Liquibase if
- Several applications or languages share the same database
- A DBA or platform team owns schema changes rather than the application developers
- You deploy the same changes to more than one database engine
- You want rollback generated for common change types, or governance features from a commercial edition
Choose Alembic if
- Your application is Python and its tables are defined with SQLAlchemy
- You want migrations drafted from model changes, then reviewed, rather than written from scratch
- You want an MIT-licensed tool with no paid tier
- Developers on the team create migrations in parallel branches and need merge support
When neither is right
- You want plain SQL files applied in order with minimal tooling: see Flyway vs Liquibase and Flyway vs Alembic.
- Your application is TypeScript: use your ORM's migration tool; see Prisma vs Drizzle ORM.
- You use Django rather than SQLAlchemy: Django has its own migrations framework built into the ORM, so Alembic does not apply.
Final recommendation
If you build a Python application on SQLAlchemy, Alembic is the natural fit: it lives in the same repository and language as your models, drafts migrations for you, and costs nothing. Review every autogenerated revision, especially for renames. If database change is a shared, cross-team concern, or you deploy to engines that SQLAlchemy does not cover well, Liquibase gives you a language-neutral changelog, free rollback commands and a commercial path to governance features, under a licence that has been FSL rather than Apache 2.0 since version 5.0.
Frequently asked questions
Can Alembic be used without SQLAlchemy models?
Yes. Autogenerate needs your SQLAlchemy MetaData, but you can write revisions by hand with op functions or raw SQL through op.execute(). Alembic itself still depends on SQLAlchemy to connect to the database.
Does Alembic autogenerate detect column renames?
No. The Alembic documentation says table and column name changes are not detected and appear as an add and a drop. Edit the generated revision to use op.alter_column() with new_column_name before you run it, or you may lose data.
Can Liquibase generate migrations from Python models?
No. Liquibase compares databases (diff, diff-changelog) or captures an existing database (generate-changelog); it does not read SQLAlchemy or other ORM models.
Can I use Liquibase in a Python project?
Yes, as an external tool: run the Liquibase CLI or its Docker image in your pipeline against changelogs stored in the repository. You need a Java runtime (17 or later for Liquibase 5.0) or Docker on the machine that runs it.
Is Liquibase free for commercial use?
Liquibase Community is free to use in production, including commercially, under FSL-1.1-ALv2. The licence restricts third parties from commercialising Liquibase Community in a way that competes with Liquibase. Liquibase Secure is the paid edition.
Sources
- Alembic documentation
- Alembic: Auto generating migrations
- Alembic: Tutorial
- Alembic: Branches
- Alembic: Batch migrations for SQLite
- Alembic on PyPI (version, licence)
- SQLAlchemy: Dialects
- Liquibase: Community licence moves to FSL
- Liquibase Community 5.0 release notes
- Liquibase: Rollback commands
- Liquibase: diff-changelog
- Liquibase pricing
- Liquibase releases (GitHub)
Checked October 2026.
How we research comparisons: our editorial method.