
Flutter: Reducing App Size Best Practices
Why is my Hello World app 20MB? Learn to shrink your Flutter app size by optimizing images, removing unused resources, filtering ABIs, and using App Bundles.

Why is my Hello World app 20MB? Learn to shrink your Flutter app size by optimizing images, removing unused resources, filtering ABIs, and using App Bundles.
Establishing TCP connection is expensive. Reuse it for multiple requests.

Yellow stripes appear when the keyboard pops up? Learn how to handle layout overflows using resizeToAvoidBottomInset, SingleChildScrollView, and tricks for chat apps.

Push works on Android but silent on iOS? Learn to fix APNs certificates, handle background messages, configure Notification Channels, and debug FCM integration errors.

Think Android is easier than iOS? Meet Gradle Hell. Learn to fix minSdkVersion conflicts, Multidex limit errors, Namespace issues in Gradle 8.0, and master dependency analysis with `./gradlew dependencies`.

On the first day of launch, I excitedly messaged my friends on KakaoTalk. "Hey, check out the app I made. Download it!"
5 minutes later, my best friend replied. "Dude, what is this? 120MB? Do you not know I'm on a budget data plan? I'll download it when I get Wi-Fi."
I was shocked. It was an app that simply logs in and views a few posts. Super apps like Baemin or Toss are only around 100MB, but my humble toy project was 120MB?
My pride as a developer was hurt. From that moment, I dedicated myself to App Diet. One week later, I succeeded in shrinking this app to 18MB. A whopping 85% reduction.
This article is a record of my struggles and the definitive guide to reducing Flutter app size.
Just as you need to measure body composition to lose weight, you need to know where the fat is to reduce app size. Cutting code blindly is meaningless. Code is just text files; it doesn't impact size much. The culprit is always in the Resources.
Flutter has a built-in powerful analysis tool. Type this in your terminal:
flutter build apk --analyze-size --target-platform android-arm64
After the build, a tree-structure analysis report appears in the terminal. Detailed info is saved as a JSON file. If you want to see this visually, you can use DevTools.
My app's autopsy results were shocking.
As you can see, the code was only 4MB. The logic I coded all night had nothing to do with the size problem. The real enemies were High-Res Images, Fat Fonts, and Unnecessary Libraries.
The first place I cut was the image folder. The 4000px high-resolution images the designer (read: me) worked on were sitting right there in the assets/images folder.
In mobile apps, PNG or JPG is luxury. You should use the WebP format created by Google. WebP is 30~50% smaller than PNG at the same quality. It also supports transparency (Alpha Channel), making it a perfect replacement for PNG.
I love using Squoosh. Drag and drop a PNG there, convert it to WebP, and watch the magic: size shrinks from 1MB to 50KB with no visible difference.
Simple graphics like logos or icons should be saved as vectors (math formulas), not bitmaps (pixel chunks).
No need to make separate @2x, @3x images for different resolutions, they don't pixelate when zoomed in, and the size is just a few KB.
To use SVG in Flutter, use the flutter_svg package.
dependencies:
flutter_svg: ^2.0.0
SvgPicture.asset(
'assets/icons/logo.svg',
width: 100,
height: 100,
);
Just this task reduced the 85MB image folder to 15MB.
After shrinking images, fonts were next. A single NotoSansKR-Bold.otf file was over 10MB.
English alphabets have 52 letters including case, maybe 100 with special characters. So font files are just a few dozen KB. But Korean is a combinational script. From 'Ga' to 'Hih', a complete set is 11,172 characters. Putting glyphs for over ten thousand characters in one file naturally makes it huge.
But will we ever use characters like "갗" or "냑" in our lives? (Unless writing a sentence like "Birch bark is called Gach".)
Boldly removing unused characters and keeping only the frequently used 2,350 characters is called a Subset Font. This reduces a 10MB font to about 3MB.
Want to reduce more? Use Google Fonts.
dependencies:
google_fonts: ^6.1.0
Text(
'Hello',
style: GoogleFonts.notoSansKr(),
);
The google_fonts package doesn't embed fonts in the app. It downloads (HTTP) necessary font files from the internet at runtime and caches them. The initial install size becomes 0MB. Of course, if you need offline support, embedding subset fonts is better.
Images and fonts reduced, but still 50MB. Why?
I unpacked the APK and saw 3 identical library files inside the lib folder.
armeabi-v7a (Old Androids)arm64-v8a (New Androids)x86_64 (Emulators/Chromebooks)For development convenience, code for all CPU architectures was stuffed in. This kindness of "Just in case a user uses a 5-year-old phone" became a size bomb.
The APK era is over. The standard Google pushes is App Bundle (.aab).
flutter build appbundle
AAB is not a finished install file. It's more like a "kit". When you upload this to the Play Store, Google generates the distribution version.
arm64-v8a code and high-res images.armeabi-v7a code and low-res images.This is called Dynamic Delivery. Without the developer worrying, Google Play creates and installs a "Tailored Suit" APK perfectly fitting the user's device. This alone reduces size by 40~50%.
What if you can't use AAB because you distribute internally or need to ship APKs directly?
You can force a diet by modifying build.gradle.
// android/app/build.gradle
android {
defaultConfig {
ndk {
// "I will only support modern phones" declaration
abiFilters 'arm64-v8a'
}
}
}
Setting abiFilters like this completely excludes .so files for other architectures during build. 99% of smartphones released these days are 64-bit (arm64-v8a). If you can give up very old devices, this method cuts size by 1/3.
But be careful. Users with 32-bit old phones won't be able to install the app or it will crash on launch. So for commercial services, AAB is the answer.
Android build tools hide a powerful beast called R8. Formerly known as ProGuard. It does two things.
UserAuthenticationManager to short names like a.b.c. Makes hacking harder and reduces text length, thus size.Flutter performs tree shaking by default in release builds. But you can turn on obfuscation for more reduction.
flutter build appbundle --obfuscate --split-debug-info=./debug-info
Using this option reduces size by another 5~10%. However, error logs (Stack Trace) will look like NullPointerException at a.b.c, so you have the hassle of keeping the debug-info file to symbolicate later.
Sad I only talked about Android? For iOS, Apple does it all for you. It's called App Thinning.
When we Archive in Xcode and upload to App Store Connect, Apple automatically slices it by device. It creates separate bitcodes for iPhone 14, iPhone SE, etc.
A point of caution during dev: Don't freak out looking at local build (Runner.app) size. Local builds include debug symbols and binaries for all architectures, so they can exceed 200MB.
To know the exact size, upload to TestFlight and check "App Store Optimized Size". That's what the actual user downloads.
Still too big after all this? There's probably a huge feature hiding in your app. Like a video editing engine or a machine learning model.
The problem is, only 1% of total users use this feature. 99% just log in and read posts. Should they have to download the video editing engine for the 1%?
This is where Deferred Loading comes in. Android calls it 'Dynamic Feature Module'.
This is possible in Flutter too.
import 'package:video_editor/main.dart' deferred as editor;
void openEditor() async {
// Download starts only when user clicks the button!
await editor.loadLibrary();
editor.runEditor();
}
Use the deferred as keyword. This way, you can keep initial install size under 10MB while building a super-app with hundreds of MBs of features.
Here is the summary of how I reduced my app from 120MB to 18MB.
flutter build apk --analyze-size.App size is a barrier to entry for users. If it exceeds 100MB, they delay installation until Wi-Fi is available, and then forget about it forever. Light apps are loved. Start your app diet right now.