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

# Schema Migrations

> Safely evolve your SQLite database schema using append-only, versioned BoutiqueDB migrations.

As your application evolves, your underlying database tables must adapt safely without causing data loss for existing users. BoutiqueDB provides an append-only, version-controlled migration system.

***

## Creating a Migration Plan

Define your migration steps in a `MigrationPlan`. Migrations are identified by unique string identifiers (e.g. `"v1_initial_schema"`, `"v2_add_avatar_url"`).

**1. Define Version 1 Initial Schema**

Create initial tables when the app is first launched.

```swift Migrations.swift theme={"theme":{"light":"github-light","dark":"github-dark"}}
import BoutiqueDB

enum AppMigrations {
    static let plan = MigrationPlan([
        Migration("v1_create_users") { conn in
            try conn.execute("""
                CREATE TABLE user_profile (
                    id TEXT PRIMARY KEY NOT NULL,
                    username TEXT NOT NULL UNIQUE,
                    createdAt REAL NOT NULL
                )
            """)
        }
    ])
}
```

**2. Add Version 2 Migration Step**

When adding new features in a app update, append a new migration step to the end of the array.

```swift Migrations.swift theme={"theme":{"light":"github-light","dark":"github-dark"}}
enum AppMigrations {
    static let plan = MigrationPlan([
        Migration("v1_create_users") { conn in
            try conn.execute("""
                CREATE TABLE user_profile (
                    id TEXT PRIMARY KEY NOT NULL,
                    username TEXT NOT NULL UNIQUE,
                    createdAt REAL NOT NULL
                )
            """)
        },
        
        Migration("v2_add_avatar_and_bio") { conn in
            try conn.execute("""
                ALTER TABLE user_profile ADD COLUMN avatarUrl TEXT;
                ALTER TABLE user_profile ADD COLUMN bio TEXT DEFAULT '';
            """)
        }
    ])
}
```

**3. Pass Migration Plan to Database Initialization**

Pass the plan into `BoutiqueDB.open`:

```swift AppStore.swift theme={"theme":{"light":"github-light","dark":"github-dark"}}
let db = try await BoutiqueDB.open(
    url: storeURL,
    migrations: AppMigrations.plan
)
```

***

## Migration Safety & Transactions

> [card] Transactional Execution
>
> All steps within a single `Migration` run inside a dedicated SQLite transaction. If a statement fails, changes are completely rolled back.

> [card] Internal Bookkeeping
>
> BoutiqueDB tracks executed migration IDs in a system table (`_boutiquedb_migrations`). Executed migrations are never re-run.

> [!WARNING]
>
> **Never Remove or Reorder Migrations**: Migrations are strictly append-only. Never modify or delete previously shipped migration IDs once an app version has been released to users!


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.