docs/developer/db-migration-checklist.md
This document provides a checklist for developers and reviewers to ensure that database migrations are implemented correctly, safely, and consistently across the project. Following these steps is mandatory for any change that alters the database schema.
The developer implementing the migration is responsible for completing these steps.
DB_VERSION constant in legacy/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java has been incremented by exactly 1.dbCreateDatabaseFromScratch within the StoreSchemaDefinition.java file.MigrationToXX.kt class file within the legacy/storage/src/main/java/com/fsck/k9/storage/migrations folder has been created, where XX is the new database version number.Migrations.kt file in the legacy/storage/src/main/java/com/fsck/k9/storage/migrations folder.The reviewer is responsible for validating these steps during the code review process.
StoreSchemaDefinition.java and Migrations.kt when rebasing. When resolving them, ensure you are correctly renumbering your migration and not overwriting someone else's.beta, release), its version number must be higher than the highest version across all branches (main, beta, release). See "Scenario B" for the detailed "jump over" strategy. Never rewrite the migration history of a public branch.When working with migrations, you'll often encounter situations where the order changes. Below are two common scenarios and how to handle them.
This happens when you are about to merge your branch, but another migration has been merged into main in the meantime.
main.MigrationToXX.kt file to MigrationToYY.kt, where YY is the new, higher version number.class MigrationToYY(...)).DB_VERSION in StoreSchemaDefinition.java to YY.Migrations.kt to use your new MigrationToYY class.Renumbering is changing the context of your migration, and you must verify its correctness again.
dbCreateDatabaseFromScratch method in StoreSchemaDefinition.java reflects the correct final schema after all migrations, including your renumbered one.beta or release)This scenario is complex and requires extreme care. It occurs when a hotfix with a migration needs to be applied to
release and/or beta, while newer migrations may already exist on beta.
The goal is to release a hotfix without breaking any user's upgrade path, regardless of which track (release/beta) they are on or switch to later.
beta, release), you must not renumber, remove, or alter it.Warning: This is a delicate process and requires careful attention to detail.
R = latest version shipped on releaseB = latest version shipped on betaM = current version on main (where your hotfix branch is based)H to max(R, B, M) + 1 (pick +2/+3 if multiple hotfixes are needed).beta or release):
MigrationToH.kt with your migration logic.DB_VERSION in StoreSchemaDefinition.java to H.Migrations.kt.dbCreateDatabaseFromScratch to the post H schema.beta first, then main immediately after:
DB_VERSION in StoreSchemaDefinition.java on beta, main to H.MigrationToH in Migrations.kt on both branches. Reuse the same migration.dbCreateDatabaseFromScratch on both branches reflects the post-H schema.H:
beta and main, ensure any unreleased migrations with version < H are updated against the new schema after H.H+1, H+2, etc., on both branches.dbCreateDatabaseFromScratch again to ensure it reflects the final schema after all migrations.Scenario: Uplift a hotfix migration MigrationTo9.kt from main to beta, while preserving existing migrations.
Initial state before uplift:
release branch is at version R=5. The last shipped migration is MigrationTo5.ktbeta branch is at version B=7. This includes MigrationTo6.kt and MigrationTo7.kt.
7 has not yet been shipped. But a version 6 has been shipped to beta users.main branch is at version M=10, it contains migrations up to MigrationTo10.kt.MigrationTo9.kt.Goal: Release the logic from MigrationTo9.kt as a hotfix to beta users without disrupting the unreleased MigrationTo7.kt.
Steps:
H=11.beta:
MigrationTo11.kt. Copy the logic from main's MigrationTo9.kt into this new file.MigrationTo7.kt.DB_VERSION in StoreSchemaDefinition.java to 11.MigrationTo11.kt in Migrations.kt.dbCreateDatabaseFromScratch to include the schema changes from MigrationTo7.kt and MigrationTo11.kt.beta, which is now on version 11.main:
main branch has a more complex history (MigrationTo8.kt, MigrationTo9.kt, MigrationTo10.kt) that must be re-evaluated now that version 11 has been introduced.MigrationTo9.kt on main is now redundant and its version number is obsolete.main to:
MigrationTo9.kt.MigrationTo11.kt file that was used on the beta branch and register it in Migrations.kt.MigrationTo8.kt as MigrationTo12.kt, MigrationTo10.kt as MigrationTo13.kt) to ensure continuity.DB_VERSION in StoreSchemaDefinition.java to 13.dbCreateDatabaseFromScratch to reflect the final schema after all migrations.Result:
release branch remains at version 5.beta ships version 11.main branch is now at version 13.6 will upgrade directly to version 11, correctly applying migrations 7 and 11.