Releasing Mobile App Updates (Major/Minor/Patch)
Post-launch app lifecycle is continuous update stream of varying weight. Patch hotfix must ship in hours. Major release with new data architecture requires weeks of preparation and phased rollout. Treating them identically means either slowing critical fixes or shipping big changes without proper safeguards.
Semantic Versioning in Mobile Context
Semver (Major.Minor.Patch) works differently in mobile than server software. versionName is marketing string users see. versionCode (Android) and CFBundleVersion (iOS) are monotonically increasing numbers stores use to determine "newer/older". Desync between them causes real problems.
Patch (x.x.N): Crash hotfix, typo correction, translation fix. Increment versionCode, change versionName minimally. For iOS can use CFBundleVersionString without changing CFBundleShortVersionString — but stores treat as update, review still required.
Minor (x.N.0): New feature, UI change, new screen. No Breaking Changes in data schema, no API contract changes. User updates — nothing breaks.
Major (N.0.0): Local DB schema change (Room migration, CoreData migration), minimum OS version change, data structure refactor in Keychain/SharedPreferences. Needs migration strategy — user's saved data from old version must correctly transfer.
Most Painful Part — Major with Data Migration
Room (Android) and CoreData (iOS) provide migration mechanisms but require careful planning. Common problem: dev adds entity field, increments @Database version, but forgets Migration object — Room throws IllegalStateException: Room cannot verify the data integrity on existing user installs.
CoreData similar — change model without lightweight migration or mapping model. App crashes on launch for existing data devices while clean install works.
Strategy for complex migrations: fallbackToDestructiveMigrationFrom (Room) only if data loss acceptable. Most cases — write explicit Migration with SQL script. Test migration on real previous-version data, not just empty DB.
Release Process
Android: Build AAB, sign, upload to Play Console. Use staged rollout — start at 5-10%, monitor Android Vitals (crash rate, ANR) for 24 hours, then expand. For patches accelerate rollout. For Major — mandatory pause at each stage.
iOS: Build via Xcode Cloud or Fastlane with gym. Upload via Transporter or fastlane deliver. Use Phased Release (7 days, 1-2-5-10-20-50-100%) for minor and major updates. For hotfix — can skip Phased Release but review takes its time.
Automate via Fastlane: lane :release with increment_build_number, tests, build, upload. CI/CD via GitHub Actions or Bitrise — each main merge post-test prepares TestFlight/Internal Testing build.
Pre-Release Checklist
- Data migrations tested on real upgrade scenarios (not just clean install)
-
versionCode/CFBundleVersionhigher than last published - Release notes written in all supported languages
- Backward compatibility with backend API verified (critical for Major)
- Firebase Crashlytics or Sentry configured and working in release
Timeline depends on update type: patch — one to two days, minor — three to five days, major — one to three weeks with migration testing.







