> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# run_startup_migrations

> Apply pending relational and vector database schema migrations

# cognee.run\_startup\_migrations

Applies all pending database schema migrations before the rest of your application starts.

```python theme={null}
await cognee.run_startup_migrations()
```

It runs two steps in sequence:

1. **Relational schema** — executes `alembic upgrade head` against your configured relational database (SQLite by default, or Postgres).
2. **Vector schema** — runs the vector adapter's `run_migrations` method for every database that needs it:
   * **Single-user mode** (`ENABLE_BACKEND_ACCESS_CONTROL=False`): migrates the single default vector engine.
   * **Multi-user mode** (`ENABLE_BACKEND_ACCESS_CONTROL=True`, the default): iterates over every dataset database and migrates each one individually. A failure for one dataset is logged and skipped; the remaining datasets continue to migrate.
   * If the active vector engine has no `run_migrations` method, Cognee logs a warning and skips that engine.
   * If the `dataset_database` table does not exist yet (a fresh database), the vector migration step is skipped with a warning instead of raising. This is handled on both SQLite (`OperationalError`, "no such table") and PostgreSQL/pgvector (`ProgrammingError` / `UndefinedTableError`).

## Entrypoints

All migration functions live in the `cognee.run_migrations` module. `run_startup_migrations` is also re-exported at the top level as `cognee.run_startup_migrations`, so it is the recommended entrypoint for most applications.

| Function                 | Import                                                                                          | Migrates                                        |
| ------------------------ | ----------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `run_startup_migrations` | `cognee.run_startup_migrations` (or `from cognee.run_migrations import run_startup_migrations`) | Relational **and** vector schema (recommended)  |
| `run_migrations`         | `from cognee.run_migrations import run_migrations`                                              | Relational schema only (`alembic upgrade head`) |
| `run_vector_migrations`  | `from cognee.run_migrations import run_vector_migrations`                                       | Vector schema only                              |

## When to call it

| Scenario                                  | Why                                                                                |
| ----------------------------------------- | ---------------------------------------------------------------------------------- |
| After upgrading the `cognee` package      | New versions may add tables or columns to the relational schema.                   |
| First run against an external database    | SQLite is auto-migrated on startup; Postgres and other external databases are not. |
| Kubernetes / Docker init containers       | Run migrations once before starting the main application pods.                     |
| Switching to a new relational DB provider | The new database starts empty and needs all migrations applied.                    |

<Note>
  For the default local setup (SQLite + LanceDB), Cognee handles migrations automatically when the API server starts. You only need to call `run_startup_migrations()` explicitly in server deployments or CI pipelines where you manage database lifecycle yourself.
</Note>

## Example

```python theme={null}
import asyncio
import cognee

async def main():
    # Apply all pending schema migrations before starting
    await cognee.run_startup_migrations()

    # Normal usage
    await cognee.add("Hello, world!", dataset_name="demo")
    await cognee.cognify()

asyncio.run(main())
```

### Kubernetes init container

Run migrations as a one-shot init container so the main pod only starts after the schema is ready:

```yaml theme={null}
initContainers:
  - name: migrate
    image: your-cognee-image:latest
    command: ["python", "-c", "import asyncio, cognee; asyncio.run(cognee.run_startup_migrations())"]
    envFrom:
      - secretRef:
          name: cognee-env
```

## Concurrency

Every migration flow runs under a single cross-process lock, so a host performs **at most one migration of any kind at a time**. If several processes start at once — multiple workers of the same server, parallel SDK runs, or several init containers — only one acquires the lock and migrates; the others block until it finishes, then re-read the stored revision and skip work that is already done. Nothing runs migrations in parallel.

Because of this, startup can block (and time-to-ready can increase) while another process holds the lock and migrates. This is expected under the [Kubernetes init container](#kubernetes-init-container) and multi-worker scenarios above — the wait is the coordination working as intended, not a hang.

The lock backend depends on your relational database:

* **Postgres** — a session-scoped advisory lock, which also serializes migrations **across hosts**. Use Postgres metadata when multiple hosts may start and migrate at the same time.
* **SQLite** — an OS advisory file lock placed next to the database file. It serializes multiple **processes on a single host** (multi-worker servers, parallel SDK runs) but **not across hosts or over NFS**.

## Errors

| Error               | Cause                                                                            | Fix                                                                                                 |
| ------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `FileNotFoundError` | `alembic.ini` or the migrations directory is missing from the installed package. | Reinstall `cognee` — the package may be corrupted or partially installed.                           |
| `MigrationError`    | Alembic exited with a non-zero return code.                                      | Check the error message logged at `ERROR` level; usually a DB connection problem or a SQL conflict. |

<Tip>
  Set `LOG_LEVEL=DEBUG` to see the full Alembic output when diagnosing migration failures.
</Tip>

## Related

* [Relational Databases](/setup-configuration/relational-databases) — configure SQLite or Postgres
* [Deployment Overview](/how-to-guides/cognee-sdk/deployment/index) — how to structure Cognee in production
* [Kubernetes (Helm)](/how-to-guides/cognee-sdk/deployment/helm) — full Kubernetes deployment guide
