Langflow Database Migration: Complete Guide to Upgrade Paths for Older Versions
Langflow uses Alembic to manage database schema changes through a directed-acyclic graph of revision scripts stored in src/backend/base/langflow/alembic/versions/, enabling upgrades from any historic version to current via CLI commands or programmatic APIs while supporting zero-downtime migrations through an Expand-Contract pattern.
Langflow stores its persistent state in a relational database managed by Alembic, the database migration tool for SQLAlchemy. Understanding the migration paths for older versions of Langflow is essential for maintaining data integrity when upgrading self-hosted instances. The migration scripts form a complete chain from the initial schema creation (revision 006b3990db50) to the latest release (revision 369268b9af8b), allowing seamless transitions between any two points in the project's history.
How Langflow Migration Chains Work
Langflow implements database versioning as a directed-acyclic graph (DAG) where each schema change is captured in a Python file under src/backend/base/langflow/alembic/versions/. Every migration script declares a unique revision ID and a down-revision (the parent script it builds upon), forming a linked chain that Alembic traverses during upgrades.
For example, the migration fd531f8868b1_fix_credential_table.py lists 2ac71eb9c3ae as its down-revision, while 369268b9af8b_add_job_id_to_vertex_build_create_job_.py builds on 182e5471b900. Some migrations like 3162e83e485f_add_auth_settings_to_folder_and_merge.py declare multiple down-revisions (0ae3a2674f32 and d9a6ea21edcd), creating branch points that Alembic merges automatically during the upgrade process.
Migration Paths Available for Older Langflow Versions
Full Upgrade to Head
The most common path migrates a database from any historic version directly to the current schema. Alembic automatically applies every intermediate migration in sequence.
alembic -c src/backend/base/langflow/alembic/alembic.ini upgrade head
This command walks the chain from the earliest migration through successive revisions like e56d87f8994a_add_optins_column_to_user.py and eb5e72293a8e_add_error_and_edit_flags_to_message.py up to the latest revision.
Targeted Upgrade to Specific Revisions
For controlled deployments, upgrade to a specific revision ID without applying later changes:
alembic -c src/backend/base/langflow/alembic/alembic.ini upgrade 182e5471b900
Replace 182e5471b900 with any revision from the versions directory (e.g., e3162c1804e6 for persistent lock state support). Alembic calculates the minimal path from the current database version to the target.
Downgrade and Rollback Procedures
Reverse migrations are supported when the script implements a safe downgrade() function:
alembic -c src/backend/base/langflow/alembic/alembic.ini downgrade 0d60fcbd4e8e
The validator in src/backend/base/langflow/utils/migration_validator.py flags missing or unsafe downgrade implementations. Note that CONTRACT phase migrations intentionally raise NotImplementedError because they are irreversible after data migration:
def downgrade() -> None:
"""CONTRACT phase – irreversible after data migration."""
raise NotImplementedError("Contract phase migrations cannot be rolled back safely.")
Handling Branch Merges
When migration history splits into parallel branches (such as when multiple features add schema changes independently), Alembic resolves these at merge points. The migration 3162e83e485f merges branches by declaring two down-revisions, ensuring databases on either branch converge to a unified schema.
Expand-Contract Pattern for Zero-Downtime
Langflow enforces a three-phase approach (EXPAND → MIGRATE → CONTRACT) for breaking changes to guarantee N-1 compatibility. The validator checks that each script declares its phase in a comment like # Phase: EXPAND and verifies that operations respect phase rules:
- EXPAND: Add new columns/tables (safe for old code)
- MIGRATE: Copy data to new structures
- CONTRACT: Remove old columns/tables (only after all nodes migrated)
Operations like drop_column are restricted to CONTRACT phases, preventing downtime during rolling upgrades.
Running Migrations Safely
CLI-Based Migration Commands
Execute migrations from the repository root using the provided configuration:
# Upgrade to latest
alembic -c src/backend/base/langflow/alembic/alembic.ini upgrade head
# Validate migration safety before deploying
python -m src.backend.base.langflow.utils.migration_validator \
src/backend/base/langflow/alembic/versions/*.py \
--json
Programmatic Migration Using Python
Embed migration logic directly into application startup or maintenance scripts:
from alembic import command
from alembic.config import Config
alembic_cfg = Config(
"src/backend/base/langflow/alembic/alembic.ini"
)
# Upgrade from current DB version to the latest
command.upgrade(alembic_cfg, "head")
Checking Current Database Version
Determine the schema revision stored in your database:
from alembic.runtime.environment import EnvironmentContext
from alembic.script import ScriptDirectory
from alembic.config import Config
cfg = Config("src/backend/base/langflow/alembic/alembic.ini")
script = ScriptDirectory.from_config(cfg)
def current_rev(conn):
context = EnvironmentContext(cfg, script, connection=conn)
with context.begin_transaction():
return context.get_current_revision()
# `conn` is a SQLAlchemy Engine/Connection
print("Current schema revision:", current_rev(conn))
Implementing Idempotent Migrations
For safety across multiple runs, migrations should check existence before altering schema. Use the pattern found in src/backend/base/langflow/utils/migration.py:
def upgrade():
bind = op.get_bind()
inspector = sa.inspect(bind)
columns = [c["name"] for c in inspector.get_columns("message")]
if "context_id" not in columns:
op.add_column("message", sa.Column("context_id", sa.String(), nullable=True))
Key Files Controlling Migration Logic
| File | Role |
|---|---|
src/backend/base/langflow/alembic/versions/ |
Directory containing every Alembic revision script (e.g., fd531f8868b1_fix_credential_table.py) |
src/backend/base/langflow/alembic/alembic.ini |
Alembic configuration specifying database URL and script locations |
src/backend/base/langflow/alembic/env.py |
Runtime environment for Alembic engine creation and logging context |
src/backend/base/langflow/utils/migration_validator.py |
Enforces Expand-Contract phases, idempotency requirements, and safe downgrade rules |
src/backend/base/langflow/utils/migration.py |
Helper utilities for existence checks and common migration operations |
Summary
- Alembic revision chain: All migrations live in
src/backend/base/langflow/alembic/versions/and link via revision IDs from006b3990db50(initial) to current. - Five upgrade paths: Full upgrade to head, targeted revision upgrade, downgrade/rollback, branch merge resolution, and Expand-Contract phased migrations.
- Safety enforcement: The
migration_validator.pyscript ensures zero-downtime compatibility and flags unsafe operations. - Execution methods: Use CLI commands with
alembic.inior Python APIs fromalembic.commandfor programmatic control. - Rollback limitations: CONTRACT phase migrations intentionally prevent downgrades after data has been permanently migrated.
Frequently Asked Questions
Can I downgrade from the latest Langflow version to a previous release?
Yes, using alembic -c src/backend/base/langflow/alembic/alembic.ini downgrade <revision-id>, but only if the migration script implements a safe downgrade() function. CONTRACT phase migrations (such as 369268b9af8b_add_job_id_to_vertex_build_create_job_.py) raise NotImplementedError because they remove deprecated structures after data migration, making rollback unsafe.
How do I migrate a database from an early Langflow 0.x release to the current version?
Run alembic -c src/backend/base/langflow/alembic/alembic.ini upgrade head. This command automatically applies every intermediate migration from the initial revision (006b3990db50) through all subsequent schema changes (like dd9e0804ebd1_add_v2_file_table.py and eb5866d51fd2_change_columns_to_be_nullable.py) up to the latest revision.
What is the Expand-Contract pattern in Langflow migrations?
It is a three-phase deployment strategy (EXPAND → MIGRATE → CONTRACT) enforced by src/backend/base/langflow/utils/migration_validator.py that ensures schema changes remain backward compatible during rolling upgrades. EXPAND phases add new structures, MIGRATE phases copy data, and CONTRACT phases remove old structures only after all application instances have migrated.
Where are the migration scripts located in the Langflow repository?
All Alembic migration files are stored in src/backend/base/langflow/alembic/versions/ within the langflow-ai/langflow repository. Each file is named with its revision ID (e.g., e3bc869fa272_fix_nullable.py) and contains the upgrade() and downgrade() functions that define the schema transformation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →