#How to run migrations
4 messages · Page 1 of 1 (latest)
Hi @tropic hedge. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Running Migrations in Convex
Normal Migration Flow
The typical steps for running a migration are:
- Modify your schema to allow both old and new values (e.g., add a new optional field or mark a field as optional).
- Define a migration using the
@convex-dev/migrationscomponent. - Push the changes with
npx convex devornpx convex deploy. - Run the migration to completion.
- Update your schema to assume the new value (this push will only succeed once all data matches). [Migrations component]
A basic migration looks like this:
export const setDefaultValue = migrations.define({
table: "users",
migrateOne: async (ctx, user) => {
if (user.optionalField === undefined) {
await ctx.db.patch(user._id, { optionalField: "default" });
}
},
});
You can run it via the CLI:
npx convex run migrations:runIt
When Schema Validation Already Fails and You Can't Deploy
If your existing data doesn't match your schema, Convex will refuse to push, blocking your deployment. Here are your options:
Option 1: Temporarily Disable Schema Validation
You can set schemaValidation: false in your schema options to bypass validation, push your code, run the migration to fix the data, and then re-enable validation:
export default defineSchema({
// ...your tables
}, { schemaValidation: false });
Steps:
- Set
schemaValidation: falseand deploy. - Run your migration to fix the data.
- Remove
schemaValidation: falseand redeploy with the corrected schema.
⚠️ Caution: When you disable schema validation, your database data may not match your schema during that window. Your code might make incorrect assumptions and crash in the meantime. [Schema Migrations Discord]
Option 2: Make Incremental, Safe Schema Changes
Instead of disabling validation, adjust your schema to be compatible with the current data first, then migrate incrementally:
- To add a field: First push it as
v.optional(...). Once all documents have the value set, push it as required. - To remove a field: First wrap it in
v.optional(...), then delete the data, then remove the field from the schema.