Convex Improved Migration

Run ordered Convex data migrations, seeds, and rebuilds from a single Plan with a CLI that blocks until completion and exits non-zero on failure.

Installation

npm install convex-improved-migration

About Convex Improved Migration

convex-improved-migration is a Convex component for running ordered data migrations, seeds, and rebuilds from a single declarative Plan. It provides a CLI that executes each Step in sequence, blocks until completion, and exits non-zero on failure so it can be integrated into deploy scripts. Steps can operate over entire tables in batches, run once per deployment, or recompute derived data when a version changes.

Benefits

Use cases

how to run data migrations in Convex without blocking the app

convex-improved-migration processes table migrations in background batched transactions using a driver action, so long backfills are not limited by the 4-minute foreground call limit or the action time limit. The CLI's apply command hands off to the background and polls status, keeping your terminal blocked until the Plan finishes. Use --no-wait to start the run and return immediately.

how to seed Convex database on every deploy

convex-improved-migration supports a seed Step type via m.seed() that runs on every apply. Write the seed body as an idempotent upsert and it will be re-executed each time npx convex-improved-migration apply runs, making it safe to call repeatedly in CI or deploy scripts.

how to backfill a new field on an existing Convex table

Define a migration Step with m.migrate(), specifying the table, a needs predicate that returns true for documents missing the new field, and a run function that returns the fields to patch. convex-improved-migration processes documents in configurable batches, skips already-migrated rows, and runs a verify pass over the table before marking the Step as Done.

how to gate a Convex deploy on migrations being complete

Run npx convex-improved-migration check before the deploy step in your CI pipeline. The check command exits 1 unless every Step in the Plan is Done, so the deploy is blocked until migrations have finished on that deployment.

Frequently asked questions

Can I run convex-improved-migration against a production deployment?

Yes. The CLI accepts deployment flags including --prod, --deployment, --preview-name, --deployment-name, --env-file, --url, and --admin-key, which pass through to npx convex run. Add --prod to target production. When the CLI prints suggested remediation commands it notes 'Add --prod to each command above' so you do not accidentally run fixes against the wrong environment.

What happens if a migration Step fails partway through?

convex-improved-migration saves the cursor position when a Step fails, so the next apply resumes from where it stopped rather than starting over. A failed Step stops the Plan and later Steps stay pending. The CLI names the failed Step, the Batch, and the cause, and suggests the next commands. Fix the cause and run apply again to resume.

How do I safely remove a completed migration Step from the Plan?

A Step removed from the Plan before it finished on a deployment blocks apply on that deployment until you restore it or record it with the mark-done command: npx convex-improved-migration mark-done <id> --reason <text>. Step ids are permanent; do not rename or reuse an id once it has been deployed.

What is the difference between migrate, once, seed, and rebuild Step types?

In convex-improved-migration, m.seed() runs on every apply and is intended for idempotent upserts. m.migrate() runs once per deployment and iterates over a table in batches, with a needs predicate to skip already-processed documents and drive a verify pass. m.once() is a single mutation that runs once per deployment with no table scan. m.rebuild() clears and recomputes derived data whenever its version field changes, a rebuild is requested, or a snapshot import is detected.

Does convex-improved-migration work with custom mutation builders or trigger wrappers?

Yes. The defineMigrations() function accepts an internalMutation option where you can pass a custom mutation builder, for example one wrapped with triggers. This lets migration Steps participate in your existing side-effect or audit infrastructure without special-casing them.

Links

Components

Open-source building blocks for your Convex app

Browse components in this category.

Loading components