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

# Data Migrations

> One-off scripts for backfilling or correcting data in the database. Some run automatically on startup for a limited time; all can be run manually.

Data migration scripts live in `backend/scripts/data_migrations/`. They handle one-off corrections, backfills, or clean-ups that cannot be expressed as a zero-downtime Alembic migration.

## How they run

Recent migrations are wired into the container startup script (`backend/scripts/start/app.sh`) and run automatically on every deploy, after Alembic migrations are applied. They are idempotent (no-op once the data is corrected) and non-fatal - a failure logs a warning and retries on the next startup.

This automatic execution is **temporary**. Each entry in `app.sh` is gated by a `TODO: Remove this after ~<date>` comment and is deleted once existing deployments have had time to upgrade. After that point the script is no longer invoked on startup.

The practical consequence: if you upgrade Open Wearables long after a migration shipped, the corresponding script may already have been removed from `app.sh` and **will not run automatically**. In that case, run it manually (see below). Scripts that were never added to `app.sh` must always be run manually.

## Prerequisites

The scripts import from the `app` package and connect to the database via the environment variables in `backend/config/.env`. You need:

* Docker Compose services running (`docker compose up -d`)
* The `app` container healthy (check with `docker compose ps`)
* A database with the latest Alembic migrations applied (`docker compose exec app uv run alembic upgrade head`)

## Running a script

All scripts are run inside the `app` container using `uv run`:

```bash theme={null}
docker compose exec app uv run python scripts/data_migrations/<script_name>.py [options]
```

### Dry run first

Every script supports a `--dry-run` flag. Always run it first — it prints the rows that would be affected without making any changes:

```bash theme={null}
docker compose exec app uv run python scripts/data_migrations/<script_name>.py --dry-run
```

### Apply changes

Once satisfied with the dry-run output, run without the flag:

```bash theme={null}
docker compose exec app uv run python scripts/data_migrations/<script_name>.py
```

<Warning>
  Scripts write directly to the database. There is no automatic rollback. Take a database snapshot before running against production.
</Warning>
