How to Reduce Mobile App Download Size on iOS and Android
Practice4 minInnovialabs editorial team
In short
Measure the per-device download size in the store consoles first, then shrink it in order: app bundles and app thinning, R8, compressed images and fonts, removing unused SDKs and moving rare content to on-demand delivery.
The short answer
Users never download your whole APK or IPA. The store builds a variant for their specific device. So the work has two steps: measure the real download size, then remove whatever ends up in it without a reason. The biggest wins usually come from:
- publishing an Android App Bundle and relying on App Thinning on iOS;
- R8 code and resource shrinking on Android, symbol stripping on iOS;
- compressing or replacing heavy images, fonts, video and animations;
- removing unused SDKs and libraries;
- moving rarely needed content to on-demand delivery.
How to measure size correctly
The size of the build file on your machine is misleading: it contains resources for every screen density and CPU architecture.
- Android. Google Play Console has an app size report with download and install sizes for common device configurations. Locally, use the APK Analyzer in Android Studio and
bundletool, which generates device-specific APKs from an.aab. - iOS. When exporting an archive in Xcode, enable the App Thinning Size Report. It lists the size for each device variant. App Store Connect also shows sizes after the build is processed.
Record the size for every release. Growth is invisible from one build to the next but obvious on a six-month chart.
Android: App Bundle and R8
An App Bundle (.aab) lets Google Play serve each device only the screen density resources, languages and native libraries it needs. It is the standard publishing format for new apps on Play.
R8 removes unused code, shortens names and, together with shrinkResources, strips unused resources:
android {
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}
After enabling R8, test the release build properly. Code reached through reflection or serialization can be removed, and you will need -keep rules for it.
iOS: App Thinning and build settings
The App Store applies App Thinning automatically: slicing delivers only the assets and architecture a device needs. Your job is to not get in its way:
- keep images in an Asset Catalog instead of loose files in the bundle, so resolution-specific delivery works;
- make sure debug symbols are stripped in release builds (upload dSYMs separately for crash reporting);
- check whether dependencies ship their own copies of the same libraries.
On-Demand Resources let you download rare content (game levels, tutorial videos) after installation. The Android equivalents are Play Asset Delivery and Play Feature Delivery.
Assets: images, fonts, media
Assets often weigh more than code. What to check:
| Asset | What to do |
|---|---|
| PNG illustrations | Convert to WebP/HEIC or vector formats |
| Icons | Use vectors (Vector Drawable, SF Symbols, SVG) |
| Fonts | Keep only the weights you use, subset glyphs |
| Video, onboarding | Stream from a server instead of bundling |
| Lottie and animations | Remove embedded bitmaps, simplify |
| Localizations | Drop languages you do not support |
Unused SDKs and dependencies
Every analytics, ads or chat SDK adds code, resources and sometimes native libraries. Audit them every quarter: which SDKs are actually used, which overlap, which are included in full for a single feature. Removing one forgotten SDK often saves more than weeks of image tuning.
Flutter and React Native specifics
- Flutter. Build with
flutter build appbundleandflutter build ipa, and use--split-debug-infowith--obfuscateto move debug info out of the binary. The--analyze-sizeflag shows what takes space. Icon fonts are tree-shaken in release builds by default. - React Native. Enable Hermes: its bytecode is usually more compact and starts faster. Turn on R8 in the Android project and check the JS bundle for heavy dependencies such as date libraries with all locales or full icon sets.
Common mistakes
- Looking at the local file size instead of store reports.
- Enabling R8 without testing the release build and crashing in production.
- Bundling onboarding videos and large images.
- Adding SDKs "for later" and never removing them.