# Migrations

Preview and validate author-owned rewrites.

## Preview and apply


```ts
const transform = (data: Database["todos"]) => ({ ...data, title: data.title.trim() });
const preview = await db.migrations.run("todos", transform, { dryRun: true });
const applied = await db.migrations.run("todos", transform);

// Specify the old type when it differs from the destination schema.
await db.migrations.run<"todos", { text: string; done?: boolean }>(
  "todos",
  old => ({ title: old.text, done: old.done ?? false }),
  { dryRun: true },
);
```

Migrations read the active author's public records, including legacy data that fails the destination schema. All transformed records are validated before the first write. Return `null` to skip a record. Applying a migration upserts the full object, removes obsolete fields, preserves IDs and original creation times, and requests a signature for each changed record. The initial author remains fixed if the active account changes.

Options include `signal` and `queue`. A queued migration uses local records and saves signed writes for explicit replay. Migrations are not atomic. `data.rows`, `data.receipts`, and `meta.receipts` preserve completed work after partial failure. There is no relay-wide schema change or multi-author migration authority.
