# Langflow Database Migrations and ORM Models: Implementation Guide

> Learn how Langflow implements database migrations using Alembic and its ORM models with SQLModel. Discover async-compatible migration techniques for robust schema management.

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

---

**Langflow uses SQLModel (a SQLAlchemy wrapper with Pydantic validation) as its ORM and Alembic for schema migrations, implementing an async-compatible migration environment with expand-contract safety validation.**

Langflow, the open-source visual framework for building LLM applications, requires robust data persistence for flows, users, and messages. According to the langflow-ai/langflow source code, the project implements a sophisticated database layer using SQLModel for type-safe ORM operations and Alembic for version-controlled schema evolution. This architecture supports both SQLite and PostgreSQL backends through an async engine pattern while enforcing strict migration safety protocols.

## How Langflow Manages Database Migrations

### The DatabaseService Migration Engine

Located in [`src/backend/base/langflow/services/database/service.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/database/service.py), the `DatabaseService` class serves as the central orchestrator for database connectivity and migration execution. The service initializes an async engine using SQLAlchemy's `create_async_engine`, automatically rewriting database URLs to use appropriate async drivers—`sqlite+aiosqlite` for SQLite and `postgresql+psycopg` for PostgreSQL.

```python
self.engine = create_async_engine(
    self.database_url,
    connect_args=self._get_connect_args(),
    **kwargs,
)

```

The service configures an async session factory using `SQLModelAsyncSession` to ensure compatibility with SQLModel's query interface:

```python
self.async_session_maker = async_sessionmaker(
    self.engine,
    class_=SQLModelAsyncSession,
    expire_on_commit=False,
)

```

When `run_migrations()` is invoked, the service delegates to Alembic's command API, loading the environment configuration from [`src/backend/base/langflow/alembic/env.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/alembic/env.py) and executing upgrades or downgrades against the async engine.

### Alembic Environment Configuration

The Alembic environment script at [`src/backend/base/langflow/alembic/env.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/alembic/env.py) bridges Alembic with Langflow's SQLModel metadata. The critical line exposing all ORM entities to Alembic is:

```python
target_metadata = SQLModel.metadata

```

This metadata object automatically collects all table definitions from SQLModel classes, enabling autogeneration of migration scripts. The environment handles async operations through `async_engine_from_config`, executing migrations within an async context using `await connection.run_sync(_do_run_migrations)`.

For PostgreSQL deployments, the environment implements distributed locking via advisory locks based on the `LANGFLOW_MIGRATION_LOCK_NAMESPACE` environment variable, preventing concurrent migration execution in multi-instance deployments.

### Expand-Contract Migration Validation

Langflow enforces database schema safety through [`src/backend/base/langflow/alembic/migration_validator.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/alembic/migration_validator.py), which implements the expand-contract pattern. This validator parses migration files using Python's `ast` module to ensure changes follow a three-phase approach:

- **EXPAND**: Add new columns or tables
- **MIGRATE**: Backfill or transform existing data  
- **CONTRACT**: Remove deprecated columns or tables

The validator flags unsafe operations—such as adding non-nullable columns without defaults or dropping columns outside the CONTRACT phase—generating structured reports that enable CI pipelines to reject risky migrations before deployment.

## Langflow ORM Models and Structure

### SQLModel-Based Entity Layer

Langflow's persistence layer uses **SQLModel**, which combines SQLAlchemy's ORM capabilities with Pydantic's data validation. All models reside under `src/backend/base/langflow/services/database/models/` and inherit from `SQLModel` with `table=True`.

Primary entities include:

- **User** ([`models/user/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/user/model.py)): Stores authentication credentials, superuser flags, and relationships to API keys and flows
- **Flow** ([`models/flow/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/flow/model.py)): Contains flow definitions as JSON graphs, linked to users and folders
- **Message** ([`models/message/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/message/model.py)): Persists conversation history with role and content fields
- **Variable** ([`models/variable/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/variable/model.py)): Key-value storage for user-specific configuration
- **File** ([`models/file/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/file/model.py)): Metadata for uploaded files including path and ownership
- **Job** ([`models/jobs/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/jobs/model.py)): Background task execution tracking
- **ApiKey** ([`models/api_key/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/api_key/model.py)): Authentication tokens linked to users
- **Folder** ([`models/folder/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/folder/model.py)): Hierarchical organization of flows
- **SSOUserProfile / SSOConfig** ([`models/auth/sso.py`](https://github.com/langflow-ai/langflow/blob/main/models/auth/sso.py)): External authentication provider integration

### Model Relationships and Field Definitions

Models define columns using SQLModel's `Field` and relationships using `Relationship`. For example, the User model establishes bidirectional relationships with API keys:

```python
class User(SQLModel, table=True):  # src/backend/base/langflow/services/database/models/user/model.py

    id: UUIDstr = Field(default_factory=uuid4, primary_key=True, unique=True)
    username: str = Field(index=True, unique=True)
    api_keys: list["ApiKey"] = Relationship(back_populates="user")

```

The `SQLModel.metadata` object collects all these definitions, making them available to Alembic for schema generation. JSON fields store complex structures like flow graphs and message content, while indexed fields optimize lookup performance for usernames and flow names.

## Running Database Migrations in Langflow

The typical migration workflow involves generating revisions through a helper script and validating them against the expand-contract rules:

```bash

# Generate a new migration from model changes

scripts/generate_migration.py "add is_active to User"

# Validate migration safety in CI

pytest src/backend/base/langflow/alembic/test_migration_validator.py

# Execute migrations

python -m langflow.services.database.migrate upgrade head

```

The [`generate_migration.py`](https://github.com/langflow-ai/langflow/blob/main/generate_migration.py) script wraps Alembic's `revision --autogenerate` command, ensuring new files are placed in `src/backend/base/langflow/alembic/versions/` with proper naming conventions.

## Summary

- Langflow uses **SQLModel** (SQLAlchemy-based) for type-safe ORM operations with Pydantic validation
- **Alembic** handles schema migrations through a custom async environment in [`src/backend/base/langflow/alembic/env.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/alembic/env.py)
- The **DatabaseService** ([`service.py`](https://github.com/langflow-ai/langflow/blob/main/service.py)) manages async engines and sessions, supporting both SQLite and PostgreSQL
- **MigrationValidator** enforces the expand-contract pattern (EXPAND → MIGRATE → CONTRACT) to prevent unsafe schema changes
- Core entities include User, Flow, Message, Variable, File, Job, ApiKey, Folder, and SSO-related models
- PostgreSQL deployments support distributed locking via `LANGFLOW_MIGRATION_LOCK_NAMESPACE`

## Frequently Asked Questions

### What ORM does Langflow use for database operations?

Langflow uses **SQLModel**, a library that combines SQLAlchemy's ORM functionality with Pydantic's data validation. This allows models to serve as both database schemas and API request/response objects. The models are defined in files under `src/backend/base/langflow/services/database/models/` using SQLModel's declarative syntax with `table=True`.

### How does Langflow handle database schema changes?

Schema changes are managed through **Alembic** with a custom async-compatible environment. The `DatabaseService` class creates an async engine and invokes Alembic commands through `run_migrations()`. All migrations must pass the `MigrationValidator`, which checks for expand-contract phase markers (EXPAND, MIGRATE, CONTRACT) to ensure zero-downtime deployments.

### Does Langflow support PostgreSQL and SQLite simultaneously?

Yes. The `DatabaseService` in [`service.py`](https://github.com/langflow-ai/langflow/blob/main/service.py) automatically detects the database URL and configures the appropriate async driver—`sqlite+aiosqlite` for SQLite or `postgresql+psycopg` for PostgreSQL. The same SQLModel definitions and Alembic migrations work across both backends, though PostgreSQL deployments additionally support advisory locking for multi-instance migration safety.

### Where are the database models defined in the Langflow repository?

All ORM models reside in `src/backend/base/langflow/services/database/models/`, with each entity typically having its own subdirectory. For example, the User model is in [`models/user/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/user/model.py), the Flow model in [`models/flow/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/flow/model.py), and the Message model in [`models/message/model.py`](https://github.com/langflow-ai/langflow/blob/main/models/message/model.py). These models are automatically registered in `SQLModel.metadata` for Alembic to track schema changes.