Implementing User Settings Migration Between Mobile App Versions
User updates the app — and all settings reset to defaults. Dark theme became light, notifications turned back on, chosen language switched to system. This happens when in new version they renamed keys in SharedPreferences / UserDefaults or changed stored value type. Without explicit migration, old values are simply ignored.
UserDefaults / SharedPreferences Migration Strategy
Basic principle — version storage settings like versioning database.
// Android
class SettingsMigration(private val prefs: SharedPreferences) {
private val PREFS_VERSION_KEY = "prefs_version"
fun migrate() {
val currentVersion = prefs.getInt(PREFS_VERSION_KEY, 0)
if (currentVersion < 1) migrateV0toV1()
if (currentVersion < 2) migrateV1toV2()
prefs.edit().putInt(PREFS_VERSION_KEY, CURRENT_VERSION).apply()
}
private fun migrateV0toV1() {
// Key rename: "dark_mode" (boolean) → "theme" (string)
val wasDark = prefs.getBoolean("dark_mode", false)
prefs.edit()
.putString("theme", if (wasDark) "dark" else "light")
.remove("dark_mode")
.apply()
}
}
Called on first launch of new version — before UI initialization.
// iOS
class SettingsMigrator {
private let defaults = UserDefaults.standard
private let versionKey = "settingsVersion"
func migrate() {
let version = defaults.integer(forKey: versionKey)
if version < 1 { migrateToV1() }
if version < 2 { migrateToV2() }
defaults.set(2, forKey: versionKey)
}
private func migrateToV1() {
// Bool → String enum
let wasDark = defaults.bool(forKey: "darkMode")
defaults.set(wasDark ? "dark" : "light", forKey: "theme")
defaults.removeObject(forKey: "darkMode")
}
}
Work Scope
- Audit current
SharedPreferences/UserDefaultskeys - Version storage settings
- Migrators for renames and type changes
- Run migration at app startup before UI initialization
Timeline
Settings migration for 1–2 versions: 0.5 day. Full audit and migration chain for several versions: 1 day.







