@@ -17,42 +17,44 @@ export const setDefaultValue = migrations.define({
1717});
1818```
1919
20- You can then run it programmatically or from the CLI. See [ below] ( #running-migrations-one-at-a-time ) .
20+ You can then run it programmatically or from the CLI. See
21+ [ below] ( #running-migrations-one-at-a-time ) .
2122
2223Migrations allow you to define functions that run on all documents in a table
2324(or a specified subset). They run in batches asynchronously (online migration).
2425
25- The component tracks the migrations state so it can avoid running twice,
26- pick up where it left off (in the case of a bug or failure along the way),
27- and expose the migration state in realtime via Convex queries.
26+ The component tracks the migrations state so it can avoid running twice, pick up
27+ where it left off (in the case of a bug or failure along the way), and expose
28+ the migration state in realtime via Convex queries.
2829
2930See the [ migration primer post] ( https://stack.convex.dev/intro-to-migrations )
30- for a conceptual overview of online vs. offline migrations.
31- If your migration is trivial and you're moving fast, also check out
31+ for a conceptual overview of online vs. offline migrations. If your migration is
32+ trivial and you're moving fast, also check out
3233[ lightweight migrations in the dashboard] ( https://stack.convex.dev/lightweight-zero-downtime-migrations ) .
3334
3435Typical steps for doing a migration:
3536
36371 . Modify your schema to allow old and new values. Typically this is adding a
37- new optional field or marking a field as optional so it can be deleted.
38- As part of this, update your code to handle both versions.
38+ new optional field or marking a field as optional so it can be deleted. As
39+ part of this, update your code to handle both versions.
39402 . Define a migration to change the data to the new schema.
40413 . Push the migration and schema changes.
41424 . Run the migration(s) to completion.
42- 5 . Modify your schema and code to assume the new value.
43- Pushing this change will only succeed once all the data matches the new schema.
44- This is the default behavior for Convex, unless you disable schema validation.
43+ 5 . Modify your schema and code to assume the new value. Pushing this change will
44+ only succeed once all the data matches the new schema. This is the default
45+ behavior for Convex, unless you disable schema validation.
4546
4647See [ this Stack post] ( https://stack.convex.dev/migrating-data-with-mutations )
4748for walkthroughs of common use cases.
4849
4950## Pre-requisite: Convex
5051
51- You'll need an existing Convex project to use the component.
52- Convex is a hosted backend platform, including a database, serverless functions,
53- and a ton more you can learn about [ here] ( https://docs.convex.dev/get-started ) .
52+ You'll need an existing Convex project to use the component. Convex is a hosted
53+ backend platform, including a database, serverless functions, and a ton more you
54+ can learn about [ here] ( https://docs.convex.dev/get-started ) .
5455
55- Run ` npm create convex ` or follow any of the [ quickstarts] ( https://docs.convex.dev/home ) to set one up.
56+ Run ` npm create convex ` or follow any of the
57+ [ quickstarts] ( https://docs.convex.dev/home ) to set one up.
5658
5759## Installation
5860
@@ -62,12 +64,13 @@ Install the component package:
6264npm install @convex - dev / migrations
6365```
6466
65- Create a ` convex.config.ts ` file in your app's ` convex/ ` folder and install the component by calling ` use ` :
67+ Create a ` convex.config.ts ` file in your app's ` convex/ ` folder and install the
68+ component by calling ` use ` :
6669
6770``` ts
6871// convex/convex.config.ts
6972import { defineApp } from " convex/server" ;
70- import migrations from " @convex-dev/migrations/convex.config" ;
73+ import migrations from " @convex-dev/migrations/convex.config.js " ;
7174
7275const app = defineApp ();
7376app .use (migrations );
@@ -77,11 +80,11 @@ export default app;
7780
7881## Initialization
7982
80- Examples below are assuming the code is in ` convex/migrations.ts ` .
81- This is not a requirement.
82- If you want to use a different file, make sure to change the examples below from
83- ` internal.migrations. * ` to your new file name, like ` internal.myFolder.myMigrationsFile.* `
84- or CLI arguments like ` migrations:* ` to ` myFolder/myMigrationsFile:* ` .
83+ Examples below are assuming the code is in ` convex/migrations.ts ` . This is not a
84+ requirement. If you want to use a different file, make sure to change the
85+ examples below from ` internal.migrations.* ` to your new file name, like
86+ ` internal.myFolder.myMigrationsFile. * ` or CLI arguments like ` migrations:* ` to
87+ ` myFolder/myMigrationsFile:* ` .
8588
8689``` ts
8790import { Migrations } from " @convex-dev/migrations" ;
@@ -92,10 +95,12 @@ export const migrations = new Migrations<DataModel>(components.migrations);
9295export const run = migrations .runner ();
9396```
9497
95- The type parameter ` DataModel ` is optional. It provides type safety for migration definitions.
96- As always, database operations in migrations will abide by your schema definition at runtime.
97- ** Note** : if you use [ custom functions] ( https://stack.convex.dev/custom-functions )
98- to override ` internalMutation ` , see [ below] ( #override-the-internalmutation-to-apply-custom-db-behavior ) .
98+ The type parameter ` DataModel ` is optional. It provides type safety for
99+ migration definitions. As always, database operations in migrations will abide
100+ by your schema definition at runtime. ** Note** : if you use
101+ [ custom functions] ( https://stack.convex.dev/custom-functions ) to override
102+ ` internalMutation ` , see
103+ [ below] ( #override-the-internalmutation-to-apply-custom-db-behavior ) .
99104
100105## Define migrations
101106
@@ -116,8 +121,8 @@ export const setDefaultValue = migrations.define({
116121
117122### Shorthand syntax
118123
119- Since the most common migration involves patching each document,
120- if you return an object, it will be applied as a patch automatically.
124+ Since the most common migration involves patching each document, if you return
125+ an object, it will be applied as a patch automatically.
121126
122127``` ts
123128export const clearField = migrations .define ({
@@ -162,20 +167,22 @@ To run it from the CLI:
162167npx convex run convex/migrations.ts:runIt # or shorthand: migrations:runIt
163168```
164169
165- ** Note** : pass the ` --prod ` argument to run this and below commands in production
170+ ** Note** : pass the ` --prod ` argument to run this and below commands in
171+ production
166172
167173Running it from the dashboard:
168174
169175![ Dashboard screenshot] ( ./dashboard_screenshot.png )
170176
171- You can also expose a general-purpose function to run your migrations.
172- For example, in ` convex/migrations.ts ` add:
177+ You can also expose a general-purpose function to run your migrations. For
178+ example, in ` convex/migrations.ts ` add:
173179
174180``` ts
175181export const run = migrations .runner ();
176182```
177183
178- Then run it with the [ function name] ( https://docs.convex.dev/functions/query-functions#query-names ) :
184+ Then run it with the
185+ [ function name] ( https://docs.convex.dev/functions/query-functions#query-names ) :
179186
180187``` sh
181188npx convex run migrations:run ' {fn: "migrations:setDefaultValue"}'
@@ -198,10 +205,10 @@ await migrations.runOne(ctx, internal.example.setDefaultValue);
198205 unless you manually specify ` cursor ` .
199206- If you provide an explicit ` cursor ` (` null ` means to start at the beginning),
200207 it will start from there.
201- - If you pass ` true ` for ` dryRun ` then it will run one batch and then throw,
202- so no changes are committed, and you can see what it would have done.
203- See [ below] ( #test-a-migration-with-dryrun )
204- This is good for validating it does what you expect.
208+ - If you pass ` true ` for ` dryRun ` then it will run one batch and then throw, so
209+ no changes are committed, and you can see what it would have done. See
210+ [ below] ( #test-a-migration-with-dryrun ) This is good for validating it does
211+ what you expect.
205212
206213## Running migrations serially
207214
@@ -228,8 +235,8 @@ Then just run:
228235npx convex run migrations:runAll # migrations:runAll is equivalent to convex/migrations.ts:runAll on the CLI
229236```
230237
231- With the ` runner ` functions, you can pass a "next" argument to run
232- a series of migrations after the first:
238+ With the ` runner ` functions, you can pass a "next" argument to run a series of
239+ migrations after the first:
233240
234241``` sh
235242npx convex run migrations:runIt ' {next:["migrations:clearField"]}'
@@ -252,24 +259,23 @@ await migrations.runSerially(ctx, [
252259- If a migration is already in progress when attempted, it will no-op.
253260- If a migration had already completed, it will skip it.
254261- If a migration had partial progress, it will resume from where it left off.
255- - If a migration fails or is canceled, it will not continue on,
256- in case you had some dependencies between the migrations.
257- Call the series again to retry.
262+ - If a migration fails or is canceled, it will not continue on, in case you had
263+ some dependencies between the migrations. Call the series again to retry.
258264
259265Note: if you start multiple serial migrations, the behavior is:
260266
261267- If they don't overlap on functions, they will happily run in parallel.
262- - If they have a function in common and one completes before the other
263- attempts it, the second will just skip it.
268+ - If they have a function in common and one completes before the other attempts
269+ it, the second will just skip it.
264270- If they have a function in common and one is in progress, the second will
265271 no-op and not run any further migrations in its series.
266272
267273## Operations
268274
269275### Test a migration with dryRun
270276
271- Before running a migration that may irreversibly change data, you can validate
272- a batch by passing ` dryRun ` to any ` runner ` or ` runOne ` command:
277+ Before running a migration that may irreversibly change data, you can validate a
278+ batch by passing ` dryRun ` to any ` runner ` or ` runOne ` command:
273279
274280``` sh
275281npx convex run migrations:runIt ' {dryRun: true}'
@@ -289,7 +295,8 @@ from a known good point as you iterate on the code.
289295
290296### Stop a migration
291297
292- You can stop a migration from the CLI or dashboard, calling the component API directly:
298+ You can stop a migration from the CLI or dashboard, calling the component API
299+ directly:
293300
294301``` sh
295302npx convex run --component migrations lib:cancel ' {name: "migrations:myMigration"}'
@@ -303,14 +310,14 @@ await migrations.cancel(ctx, internal.migrations.myMigration);
303310
304311### Get the status of migrations
305312
306- To see the live status of migrations as they progress, you can query it via the CLI:
313+ To see the live status of migrations as they progress, you can query it via the
314+ CLI:
307315
308316``` sh
309317npx convex run --component migrations lib:getStatus --watch
310318```
311319
312- The ` --watch ` will live-update the status as it changes.
313- Or programmatically:
320+ The ` --watch ` will live-update the status as it changes. Or programmatically:
314321
315322``` ts
316323const status: MigrationStatus [] = await migrations .getStatus (ctx , {
@@ -343,10 +350,12 @@ npx convex deploy --cmd 'npm run build' && npx convex run convex/migrations.ts:r
343350
344351### Override the internalMutation to apply custom DB behavior
345352
346- You can customize which ` internalMutation ` implementation the underly migration should use.
353+ You can customize which ` internalMutation ` implementation the underly migration
354+ should use.
347355
348- This might be important if you use [ custom functions] ( https://stack.convex.dev/custom-functions )
349- to intercept database writes to apply validation or
356+ This might be important if you use
357+ [ custom functions] ( https://stack.convex.dev/custom-functions ) to intercept
358+ database writes to apply validation or
350359[ trigger operations on changes] ( https://stack.convex.dev/triggers ) .
351360
352361Assuming you define your own ` internalMutation ` in ` convex/functions.ts ` :
@@ -361,15 +370,14 @@ export const migrations = new Migrations(components.migrations, {
361370});
362371```
363372
364- See [ this article] ( https://stack.convex.dev/migrating-data-with-mutations )
365- for more information on usage and advanced patterns.
373+ See [ this article] ( https://stack.convex.dev/migrating-data-with-mutations ) for
374+ more information on usage and advanced patterns.
366375
367376### Custom batch size
368377
369378The component will fetch your data in batches of 100, and call your function on
370- each document in a batch.
371- If you want to change the batch size, you can specify it.
372- This can be useful if your documents are large, to avoid running over the
379+ each document in a batch. If you want to change the batch size, you can specify
380+ it. This can be useful if your documents are large, to avoid running over the
373381[ transaction limit] ( https://docs.convex.dev/production/state/limits#transactions ) ,
374382or if your documents are updating frequently and you are seeing OCC conflicts
375383while migrating.
@@ -393,12 +401,11 @@ await migrations.runOne(ctx, internal.migrations.clearField, {
393401### Parallelizing batches
394402
395403Each batch is processed serially, but within a batch you can have each
396- ` migrateOne ` call run in parallel if you pass ` parallelize: true ` .
397- If you do so, ensure your callback doesn't assume that each call is isolated.
398- For instance, if each call reads then updates the same counter, then multiple
399- functions in the same batch could read the same counter value, and get off by
400- one.
401- As a result, migrations are run serially by default.
404+ ` migrateOne ` call run in parallel if you pass ` parallelize: true ` . If you do so,
405+ ensure your callback doesn't assume that each call is isolated. For instance, if
406+ each call reads then updates the same counter, then multiple functions in the
407+ same batch could read the same counter value, and get off by one. As a result,
408+ migrations are run serially by default.
402409
403410``` ts
404411export const clearField = migrations .define ({
@@ -411,8 +418,9 @@ export const clearField = migrations.define({
411418### Shorthand running syntax:
412419
413420For those that don't want to type out ` migrations:myNewMigration ` every time
414- they run a migration from the CLI or dashboard, especially if you define your migrations
415- elsewhere like ` ops/db/migrations:myNewMigration ` , you can configure a prefix:
421+ they run a migration from the CLI or dashboard, especially if you define your
422+ migrations elsewhere like ` ops/db/migrations:myNewMigration ` , you can configure
423+ a prefix:
416424
417425``` ts
418426export const migrations = new Migrations (components .migrations , {
0 commit comments