# Langflow Database Migration: Complete Guide to Upgrade Paths for Older Versions

> Explore Langflow database migration paths. Upgrade seamlessly from older versions using Alembic with CLI commands or APIs, ensuring zero-downtime.

- Repository: [Langflow/langflow](https://github.com/langflow-ai/langflow)
- Tags: migration-guide
- Published: 2026-02-24

---

**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`](https://github.com/langflow-ai/langflow/blob/main/fd531f8868b1_fix_credential_table.py) lists `2ac71eb9c3ae` as its down-revision, while [`369268b9af8b_add_job_id_to_vertex_build_create_job_.py`](https://github.com/langflow-ai/langflow/blob/main/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`](https://github.com/langflow-ai/langflow/blob/main/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.

```bash
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`](https://github.com/langflow-ai/langflow/blob/main/e56d87f8994a_add_optins_column_to_user.py) and [`eb5e72293a8e_add_error_and_edit_flags_to_message.py`](https://github.com/langflow-ai/langflow/blob/main/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:

```bash
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:

```bash
alembic -c src/backend/base/langflow/alembic/alembic.ini downgrade 0d60fcbd4e8e

```

The validator in [`src/backend/base/langflow/utils/migration_validator.py`](https://github.com/langflow-ai/langflow/blob/main/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:

```python
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:

```bash

# 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:

```python
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:

```python
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`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/utils/migration.py):

```python
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`](https://github.com/langflow-ai/langflow/blob/main/fd531f8868b1_fix_credential_table.py)) |
| [`src/backend/base/langflow/alembic/alembic.ini`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/alembic/alembic.ini) | Alembic configuration specifying database URL and script locations |
| [`src/backend/base/langflow/alembic/env.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/alembic/env.py) | Runtime environment for Alembic engine creation and logging context |
| [`src/backend/base/langflow/utils/migration_validator.py`](https://github.com/langflow-ai/langflow/blob/main/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`](https://github.com/langflow-ai/langflow/blob/main/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 from `006b3990db50` (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.py`](https://github.com/langflow-ai/langflow/blob/main/migration_validator.py) script ensures zero-downtime compatibility and flags unsafe operations.
- **Execution methods**: Use CLI commands with [`alembic.ini`](https://github.com/langflow-ai/langflow/blob/main/alembic.ini) or Python APIs from `alembic.command` for 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`](https://github.com/langflow-ai/langflow/blob/main/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`](https://github.com/langflow-ai/langflow/blob/main/dd9e0804ebd1_add_v2_file_table.py) and [`eb5866d51fd2_change_columns_to_be_nullable.py`](https://github.com/langflow-ai/langflow/blob/main/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`](https://github.com/langflow-ai/langflow/blob/main/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`](https://github.com/langflow-ai/langflow/blob/main/e3bc869fa272_fix_nullable.py)) and contains the `upgrade()` and `downgrade()` functions that define the schema transformation.