Skip to main content
When you change the schema (add a field, rename a table, change a type), vly handles the migration automatically. This page covers what happens and when to intervene.

What gets migrated automatically

Adding a field

New optional field — instant. New required field with default — vly backfills.

Renaming a field

vly copies values from old field to new, drops old. Done in one transaction per row.

Removing a field

Field disappears from the validator; data on existing rows is no longer accessible (still on disk; cleaned up over time).

Adding an index

Index built in the background; queries use the new index once it’s ready.

What needs your attention

Adding a required field with no default

vly will refuse the migration. Either provide a default in the schema, or run a one-shot mutation to populate the field, then make it required.

Changing a field type

Number → String etc. — vly asks you for a conversion function ((oldValue) => newValue).

Removing a table

Lossy. vly confirms with a clear warning and lists how many rows will become inaccessible.

Manual one-shot migrations

For complex transformations:
convex/migrations/2026-04-18-normalize-emails.ts
Run via vly convex run migrations.2026-04-18-normalize-emails.

Tips

Schema changes are part of version history. Roll back the code; the schema stays. For destructive changes, plan a separate cleanup.
Stage schema changes separately from feature changes when possible. Easier to roll back independently.

Schema

Schema definition.

Version history

Roll back caveats.

Background jobs

For very long migrations.
Last modified on April 18, 2026