Skip to main content
Version: 1.13.x

Database migrations

Langflow stores application data such as flows, users, and API keys in a SQL database.

When you upgrade Langflow or connect to a new empty database, Langflow must keep the database schema aligned with the application models.

By default, the Langflow database uses SQLite, and uses Alembic for SQL database migrations.

This page explains when migrations run and how to run and repair migrations safely.

To move users, flows, files, and knowledge bases to another Langflow installation, see Move to a new Langflow instance.

Default migrations behavior and triggers​

Most Langflow users never need to run a database migration. When you start Langflow, or restart a container after upgrading the Langflow image, pending Alembic migrations run as part of database initialization.

Langflow includes Alembic revision scripts with the package. On startup, Langflow connects to the database at LANGFLOW_DATABASE_URL or the default langflow.db file, ensures the required tables exist, checks the database schema against the current models, and then applies any pending Alembic upgrades to bring the schema to its head revision.

Alembic records the applied revision in the alembic_version table.

Other events that trigger Alembic checks are a first Langflow startup against a new SQLite file or empty PostgreSQL database, upgrading to a Langflow version that includes new Alembic revisions, or pointing LANGFLOW_DATABASE_URL at an empty database.

Upgrade Langflow safely​

To upgrade Langflow or change the database URL in a deployment that already has data, you may need a database migration. To migrate your database, do the following:

  1. Stop Langflow.

  2. Back up the database.

    If you're using SQLite, copy the langflow.db file. The default path depends on your install method and whether LANGFLOW_SAVE_DB_IN_CONFIG_DIR is set. For more information, see Memory management options.

    If you're using PostgreSQL, make a logical backup with pg_dump, or use your database provider's snapshot. For more information, see enterprise backup guidance.

  3. Export any flows you want to save as JSON. For more information, see Import and export flows.

  4. Upgrade the Langflow package or container image to the latest version, keeping the same LANGFLOW_DATABASE_URL or the same SQLite path.

    uv pip install langflow -U
  5. Start a single Langflow instance, so database migrations run without concurrent database writes.

  6. Confirm that startup succeeds.

  7. If startup reports a schema mismatch, run langflow migration to inspect the problem and restore from backup if needed. For more information, see langflow migration CLI.

UTC timestamps in Langflow 1.13​

Langflow 1.13 adopts SQLModel's UTC datetime storage for previously inferred datetime fields. PostgreSQL converts 19 timestamp columns across users, API keys, files, flows, MCP servers, SSO user profiles, messages, transactions, vertex builds, traces, and spans to TIMESTAMP WITH TIME ZONE. The migration interprets existing values as UTC, matching Langflow's timestamp writers, and preserves microseconds and null values independently of the PostgreSQL session timezone. If another application wrote local times directly to these columns, reconcile those values before upgrading: their original timezone cannot be recovered from the stored timestamps.

Follow the upgrade procedure above with all old backend instances, workers, and listeners stopped. Start one upgraded backend to run the migration before starting the remaining upgraded processes. This change does not support mixing older and newer application versions against the same database: older schema checks expect timestamps without timezone information. PostgreSQL takes exclusive locks on the affected tables and may rewrite their data and indexes, so allow a maintenance window sized for the message and tracing tables.

SQLite needs no timestamp schema conversion; SQLModel now restores UTC timezone information when reading historical timestamps. Legacy flow and message timestamps and trace filters without an offset continue to be interpreted as UTC. Custom code that writes directly through SQLModel must supply aware timestamps, such as datetime.now(timezone.utc); naive datetime parameters are rejected by the new SQLModel type. Datetime fields returned by the ORM are now aware, and API fields without a custom serializer include a UTC offset.

To reverse this timestamp conversion, stop all upgraded processes and use the 1.13 migration code to downgrade revision f2a7c9e4b681 to its parent 9d7e2a6c4b81. The downgrade converts the affected PostgreSQL values back to naive UTC, preserving the represented instants. This reverses only the timestamp change. Before starting an older release, follow the rollback procedures for any other intervening migrations; restoring the pre-upgrade backup is the fallback.

Switch from SQLite to PostgreSQL​

Changing LANGFLOW_DATABASE_URL from SQLite to PostgreSQL does not copy existing SQLite data into PostgreSQL. Langflow initializes and migrates the new database schema, and your previous SQLite file remains where it was.

To copy everything from SQLite into PostgreSQL, stop Langflow and run langflow convert-sqlite-to-postgres:

langflow convert-sqlite-to-postgres \
--source sqlite:////path/to/langflow.db \
--target postgresql://user:password@host:5432/langflow

A command line is visible to other users of the machine, so to keep the PostgreSQL password out of it, set LANGFLOW_MIGRATION_SOURCE_URL and LANGFLOW_MIGRATION_TARGET_URL instead of passing --source and --target. If both are given, the options win.

The SQLite database must already be on the schema of the Langflow version you run the command with, so start that version against it once first. If you copy the SQLite file before converting, use sqlite3 langflow.db ".backup copy.db" or VACUUM INTO. Langflow runs SQLite in WAL mode, so a plain file copy can come out empty.

The command creates the PostgreSQL schema, copies every row in one transaction, and checks each table's row count before committing. If anything is refused, such as a value PostgreSQL does not accept or a target database that already belongs to another instance, nothing is written and the command lists the problems.

SQLite never enforced Langflow's foreign keys, so deleting a user or clearing a flow's traces can leave rows that point at a deleted row. PostgreSQL rejects those rows, so the command refuses them by default and lists each table, column, and row count. To copy without them, rerun with --drop-orphans. Rows that PostgreSQL would have deleted along with their parent (ON DELETE CASCADE) are left out, keys it would have cleared (ON DELETE SET NULL) are set to NULL, and the command reports how many rows it handled for each. Keep the same LANGFLOW_SECRET_KEY when you point Langflow at the new database, or stored credentials can't be decrypted.

To run the command from another program, add --json. It then writes one JSON object per line to standard output: progress as it checks the source, prepares the target, and copies rows, item for each copied table, error or decision_needed for anything it refuses, and a final report. Each problem carries a stable code, logs go to standard error, and the exit code is non-zero if anything was refused or failed. A run stopped by SIGINT or SIGTERM ends with an error whose code is interrupted, and exits with 130 for SIGINT or 143 for SIGTERM.

To move only your flows instead, do the following:

  1. Export flows, and note any global variables or credentials.
  2. Provision PostgreSQL 15+ and set LANGFLOW_DATABASE_URL as described in Configure an external PostgreSQL database.
  3. If required, install PostgreSQL driver extras, for example uv pip install "langflow[postgresql]".
  4. Start Langflow. The new PostgreSQL schema is created.
  5. Import the exported flows and recreate secrets or variables as needed.

Migration logging​

Alembic output is written to a log file by default at alembic/alembic.log under the Langflow config directory (LANGFLOW_CONFIG_DIR). Relative LANGFLOW_ALEMBIC_LOG_FILE values are also resolved against that config directory. In read-only or hardened containers, that path may not be writable, and Langflow will fall back to stdout and continue the migration.

Migration environment variables​

VariablePurpose
LANGFLOW_​ALEMBIC_​LOG_​TO_​STDOUTSet to true to send Alembic migration output to stdout.
LANGFLOW_​ALEMBIC_​LOG_​FILEAbsolute or relative path for the Alembic log file when not logging to stdout. Relative paths resolve under the Langflow config directory.
LANGFLOW_​MIGRATION_​LOCK_​TIMEOUT_​SSeconds to wait for the PostgreSQL migration advisory lock. Default: 300.
LANGFLOW_​MIGRATION_​LOCK_​NAMESPACEOptional namespace for the Alembic PostgreSQL advisory lock. The default lock key coordinates instances that share a database. Set this variable to isolate different Langflow deployments that share one PostgreSQL server. Use the same value on every instance in that deployment.

Troubleshooting​

For troubleshooting database migrations, see Langflow upgrade issues.

See also​

Was this page helpful?

Support
Search