Repository navigation
Docs: Run step-by-step migrations in transactions - #3876
Merged
simolus3 merged 1 commit intoOct 14, 2026
Merged
Conversation
Wrap each step of the runMigrationSteps example in a transaction and explain why: without one, a step that fails or is interrupted halfway stays partially applied while the stored schema version is not updated, so the step fails when it runs again on the next start. Also note that pragmas like foreign_keys have to be changed outside of the transaction, which matters for alterTable as well. Closes #3725
simolus3
approved these changes
Oct 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3725
In #3725, an app was terminated during a step-by-step migration after a step had already renamed a column. The stored schema version was still the old one, so the step ran again on the next start and
renameColumnfailed. As discussed in the issue, the way to avoid this is to run migration steps in transactions, which the step-by-step migrations page didn't cover yet.Changes:
runMigrationStepsexample onmigrations/step_by_step.mdnow runs each step indatabase.transaction, using the wrapper suggested in the issue.runMigrationStepsstores the schema version after each step. It mentions wrapping the wholerunMigrationStepscall in one transaction as the alternative, and thatPRAGMA foreign_keyshas to be changed outside the transaction, which also affectsalterTable.docs/lib/src/generated_snippets.dartis regenerated withbuild_runner. Only thestep_by_step.dartentry changed; the same build ondevelopleaves the file untouched.Testing, in
docs/:dart format -o none --set-exit-if-changed .,dart analyze --fatal-infos --fatal-warnings,dart run drift_dev analyzeanddart testpass.dart run tool/build_search_index.dartrenders all pages, and the rendered step-by-step page contains the new section and the updated snippet. I didn't run the fulltool/build.sh.StepByStep2snippet by overridingcustomStatementin a database subclass to throw right after theADD COLUMN "due_date"statement of the 1 to 2 step, then opened the database again. With the old snippet, the second open fails withduplicate column name: due_datebecause the column was kept whileuser_versionwas still 1. With the new snippet, the step is rolled back and the second open migrates to version 3.no such column: "legacy_body") and succeeds with one; when the 2 to 3 step is interrupted, per-step transactions keep the completed 1 to 2 step while a single transaction aroundrunMigrationStepsrolls back to version 1; andalterTableinside a per-step transaction fails withFOREIGN KEY constraint failed(or deletes the referencing rows if they useON DELETE CASCADE) unless foreign keys were disabled before the transaction.