How to Reduce Android App Size for Google Play (2026 Guide)
Google Play enforces hard download-size limits and users uninstall bloated apps. Here is how to measure, cut, and keep your Android app size down — with specific wins for Expo and Flutter apps.
Google Play enforces a compressed download-size limit of 500 MB for the base module of an Android App Bundle (raised from 200 MB in 2025), and beyond store policy, every extra megabyte measurably hurts your install conversion rate and retention. This guide shows you how to measure your real download size, which fixes cut the most bytes in Expo and Flutter apps, and how to stay under the limits without gutting your features.
Google Play app size limits at a glance
All limits are based on compressed download size, estimated by Play Console when you upload your bundle:
| App component | Download size limit |
|---|---|
| Base module | 500 MB |
| Individual feature modules | 500 MB |
| Individual asset packs | 1.5 GB |
| Cumulative install-time total | 4 GB |
| On-demand / fast-follow asset packs | 30 GB (34 GB overall) |
A few details that trip people up:
- Apps larger than 200 MB trigger a "large app" warning dialog for users on mobile data.
- Apps above 1 GB must target Android 5.0 (API 21) or higher.
- Legacy APK uploads (instead of AAB) are still capped at 100 MB — one more reason to publish with an App Bundle.
Step 1: Measure before you cut
Guesswork wastes time. Get the real numbers first:
- Play Console app size report — after uploading, Play Console shows the estimated download size per device configuration. This is the number Google enforces and the one users see.
- bundletool —
bundletool build-apks --mode=universalandbundletool get-size totalapproximate what Play Console will report, locally. - Android Studio APK Analyzer — for uploaded artifacts, it breaks down exactly which DEX entries, resources,
lib/binaries, and assets eat your budget.
Fix the biggest bucket first. For React Native apps that is almost always lib/ (native .so files) and bundled images; for Flutter it is usually the engine plus assets.
Step 2: The high-impact fixes
Enable R8 code and resource shrinking
In android/app/build.gradle, make sure release builds shrink:
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}R8 removes unused Java/Kotlin bytecode; resource shrinking strips layouts and drawables no longer referenced. Combined, they routinely save 20–40% on real-world apps.
Ship per-ABI builds (or let the AAB do it)
Uploading an App Bundle instead of a legacy APK means Play generates per-device APKs, so an arm64-only phone never downloads x86 or armeabi-v7a native libraries. If you must distribute APKs directly, use ABI splits. This alone often halves the native-library footprint users actually download.
Compress and modernize images
- Convert PNG/JPG assets to WebP (typically 25–35% smaller at equal quality).
- Replace raster icons with vector drawables where possible.
- Move large media out of the bundle entirely and stream it from a CDN, or ship it as an install-time/on-demand asset pack so it doesn't count against the base module.
Remove dead code and resources
- Delete unused locales:
resConfigs "en", "pt", "es"(orandroidResources.localeFiltersin newer AGP) drops every other translation Android libraries carry by default. - Run a dependency audit — one heavy analytics or ads SDK can add 5–10 MB of DEX and native code.
Expo-specific wins
- Make sure Hermes is enabled (default in recent SDKs) — it shrinks bytecode and improves startup.
- Use
npx expo-optimizeto compress bundled images. - Check
expo-updatesembedded assets: old embedded manifests can keep dead assets in the binary.
Flutter-specific wins
- Build with
flutter build appbundle --split-per-abi(or rely on the AAB's per-device splits). - Enable icon tree shaking (
flutter build appbundle --tree-shake-icons, on by default in release). - Use
--obfuscate --split-debug-infoto move symbol files out of the binary. - For very large games, use deferred components to download assets after install.
Step 3: Keep it lean
App size creeps back with every feature. Add a size budget to CI (fail the build when download size grows more than, say, 2 MB), and re-check the Play Console size report each release.
Start from a lean base
The cheapest megabytes are the ones you never ship. BowlerKit's Expo and Flutter templates are tuned for small download sizes out of the box — Hermes, R8, per-ABI delivery, and optimized assets are pre-configured, and the Play Store assets guide walks you through the rest of your release checklist. See the quick start to generate a project in one command.