Deploying Flutter Apps to Apple App Store and Google Play
Shipping to Production: Flutter App Store Deployment Checklist
When it comes to deploying flutter apps, the journey from a local development environment to the hands of millions of global users is both an exciting milestone and a highly technical operation. While Flutter drastically simplifies cross-platform UI development, the final mile of release engineering requires navigating two distinct, highly secure, and opinionated ecosystems: Apple's App Store and Google's Play Store.
Understanding the nuances of code signing, provisioning profiles, build optimization, and store compliance is what separates a fragile, manual release process from a robust, automated deployment pipeline. If you are still evaluating your mobile strategy, understanding why Flutter is the premier choice for cross-platform development can provide valuable context on how Flutter's architecture simplifies these downstream deployment steps.
+-----------------------------------------------------------------+
| Flutter Source Code |
+-----------------------------------------------------------------+
|
v
+--------------------------------------+
| Flutter Release Builds |
+--------------------------------------+
/ \
/ \
v v
+---------------------------+ +---------------------------+
| Android App Bundle | | iOS App Store Package |
| (.aab) | | (.ipa) |
+---------------------------+ +---------------------------+
| |
v v
+---------------------------+ +---------------------------+
| Google Play Console | | App Store Connect |
+---------------------------+ +---------------------------+
| |
v v
+---------------------------+ +---------------------------+
| Google Play Store | | Apple App Store |
+---------------------------+ +---------------------------+
To ensure a seamless launch, developers must adhere to a strict deployment checklist. This guide provides an exhaustive, production-grade walkthrough of the entire release lifecycle, detailing how to compile optimized flutter release builds, configure platform-specific environments, submit app to app store, and publish android app play store with zero downtime.
Preparing Release Builds: Bundles, App Bundles, and IPA Formats
Before uploading your application to either store, you must compile your Dart code and native assets into highly optimized, platform-specific release binaries. Debug builds of Flutter contain the Dart VM and JIT (Just-In-Time) compiler to enable Hot Reload. Release builds, however, use AOT (Ahead-Of-Time) compilation, stripping away debugging overhead, enabling tree-shaking, and compiling directly to native ARM machine code.
Android: Android App Bundle (AAB) vs. APK
Historically, developers distributed Android applications using the Android Package (APK) format. Today, Google Play requires the Android App Bundle (AAB) format for all new applications.
Unlike a monolithic APK, which contains resources and compiled binaries for every possible screen density, CPU architecture, and language, an AAB is an upload format. When a user downloads your app, Google Play uses the AAB to generate a highly optimized, dynamic APK tailored specifically to that user's device configuration. This typically reduces the download size by 20% to 60%.
To generate a production-ready Android App Bundle, run the following command in your terminal:
flutter build appbundle --releaseFor advanced optimization, you can obfuscate your Dart code to protect your intellectual property from reverse engineering, and split debug symbols to keep your binary size minimal while retaining the ability to de-obfuscate crash logs:
flutter build appbundle --release \
--obfuscate \
--split-debug-info=build/app/outputs/symbolsiOS: The IPA Format
On iOS, the final distribution package is an IPA (iOS App Store Package) file. This is a compressed archive containing the compiled binary, assets, frameworks, and code signatures required by Apple's secure runtime environment.
To compile an IPA, you must first build an Xcode archive and then export it. Flutter simplifies this process with a unified command:
flutter build ipa --release \
--obfuscate \
--split-debug-info=build/ios/outputs/symbolsThis command compiles your Dart code into native iOS assembly, configures the Xcode workspace, and generates an .xcarchive directory. From this archive, you can export the signed .ipa file using Xcode or command-line tools like Fastlane.
Managing App Versioning
Both platforms require strict version management. This is configured globally in your Flutter project's pubspec.yaml file using the version property:
version: 1.4.2+18This version string is split into two distinct components by the build system:
- Version Name (
1.4.2): The semantic version displayed to users in the app stores. - Version Code (
18): An internal, monotonically increasing integer used by the operating systems and app stores to determine upgrade paths. Every build uploaded to the stores must have a higher version code than the previous one.
During compilation, Flutter automatically injects these values into the native configuration files:
- Android: Maps to
versionNameandversionCodeinandroid/app/build.gradle. - iOS: Maps to
CFBundleShortVersionString(Bundle Version String (Short)) andCFBundleVersion(Bundle Version) inios/Runner/Info.plist.
| Platform | Build Artifact | Primary Format | Versioning Parameter (User-Facing) | Versioning Parameter (Internal) |
| :--- | :--- | :--- | :--- | :--- |
| Android | Android App Bundle | .aab | versionName (e.g., 1.4.2) | versionCode (e.g., 18) |
| iOS | iOS App Store Package | .ipa | CFBundleShortVersionString | CFBundleVersion |
iOS App Store Submission: Certificates, Provisioning Profiles, and App Store Connect
Deploying flutter apps to Apple's ecosystem requires navigating Apple's rigorous code-signing architecture. Code signing guarantees that your application originates from a known, verified source and has not been modified since it was signed.
+-----------------------------------------------------------------+
| Apple Developer Account |
+-----------------------------------------------------------------+
| |
v v
+------------------+ +------------------+
| Certificate | | App ID |
| (Distribution) | | (Bundle Identifier) |
+------------------+ +------------------+
\ /
\ /
v v
+-------------------------------------------------+
| Provisioning Profile |
+-------------------------------------------------+
|
v
+-------------------------------------------------+
| Xcode / IPA |
+-------------------------------------------------+
Step 1: Establish Your Code Signing Assets
To sign and submit app to app store, you must have an active Apple Developer Program membership. Once enrolled, you need to generate three core assets:
- Distribution Certificate: Identifies your organization and authorizes you to submit apps to the App Store.
- App ID: A unique identifier for your application, matching your iOS Bundle Identifier (e.g.,
com.vyrova.tech.analytics). - Provisioning Profile: A secure cryptographic link issued by Apple that binds your Distribution Certificate, App ID, and target device constraints together. For App Store distribution, you will use an App Store Distribution Provisioning Profile.
To generate these assets:
- Open Xcode on your macOS machine.
- Navigate to Xcode > Settings > Accounts and sign in with your Apple ID.
- Select your team and click Manage Certificates.
- Click the + icon and select Apple Distribution. Xcode will generate a Certificate Signing Request (CSR), submit it to Apple, and install the signed certificate into your local Keychain.
Step 2: Configure Xcode Project Settings
Open the ios/Runner.xcworkspace file in Xcode. Select the root Runner project in the project navigator, and under the Signing & Capabilities tab, configure the following:
- Automatically manage signing: For most teams, checking this box allows Xcode to handle provisioning profile creation and updates automatically.
- Team: Select your registered Apple Developer Program team.
- Bundle Identifier: Ensure this matches the App ID registered in your Apple Developer Account.
<!-- Example of Bundle Identifier in ios/Runner/Info.plist -->
<key>CFBundleIdentifier</key>
<string>com.vyrova.tech.analytics</string>Step 3: Create the App Record in App Store Connect
Before uploading your binary, you must create a placeholder record in App Store Connect:
- Log in to App Store Connect.
- Navigate to Apps and click the + button to create a New App.
- Select iOS, enter your app's name, primary language, and select your Bundle ID.
- Provide a unique SKU (a unique string for your app, such as
vyrova_analytics_ios_prod). - Choose Full Access or restrict access to specific team members.
Step 4: Uploading the IPA via Fastlane
While you can upload your build directly from Xcode's Organizer window, automating this step using Fastlane ensures consistency and integrates seamlessly into CI/CD pipelines.
First, initialize Fastlane in your ios directory:
cd ios && fastlane initConfigure your ios/fastlane/Fastfile to automate the build and upload process:
default_platform(:ios)
platform :ios do
desc "Build and upload release to App Store Connect TestFlight"
lane :beta do
# Ensure certificates and profiles are up to date
get_certificates # Equivalent to sigh
get_provisioning_profile # Equivalent to cert
# Increment build number based on TestFlight
increment_build_number(
build_number: latest_testflight_build_number + 1
)
# Build the Flutter IPA
sh("flutter build ipa --release")
# Upload to TestFlight
upload_to_testflight(
username: "deploy@vyrova.tech",
app_identifier: "com.vyrova.tech.analytics",
skip_waiting_for_build_processing: true
)
end
endRun the lane to execute the deployment:
fastlane betaAndroid Play Store Submission: Keystore Generation, Play Console Setup
To publish android app play store, you must cryptographically sign your Android App Bundle. Android uses this digital signature to verify the author of the application and to ensure that updates are authentic and secure.
Step 1: Generate a Secure Upload Keystore
An upload keystore is a secure binary file containing a private cryptographic key. You must keep this key secure; if lost, you will not be able to upload updates to your application unless you have enabled Google Play App Signing.
To generate a keystore, execute the following command in your terminal:
keytool -genkey -v -keystore ~/upload-keystore.jks \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias uploadThis command prompts you to set a secure password and provide organizational details. It outputs a file named upload-keystore.jks in your home directory.
Step 2: Configure Flutter to Use the Keystore
To reference this keystore securely without committing sensitive passwords to your version control system, create a file named android/key.properties (and ensure it is added to your .gitignore file):
storePassword=your_secure_keystore_password
keyPassword=your_secure_key_password
keyAlias=upload
storeFile=/Users/username/upload-keystore.jksNext, modify your android/app/build.gradle file to load these properties and apply them to your release build configuration:
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
...
signingConfigs {
release {
if (keystorePropertiesFile.exists()) {
storeFile = file(keystoreProperties['storeFile'])
storePassword = keystoreProperties['storePassword']
keyAlias = keystoreProperties['keyAlias']
keyPassword = keystoreProperties['keyPassword']
}
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}Step 3: Configure Google Play Console
- Log in to the Google Play Console.
- Click Create app, fill in your app name, default language, and specify whether it is an app or a game, and free or paid.
- Navigate to Setup > App integrity and opt-in to Play App Signing. This allows Google to manage your app's signing key securely. If you lose your upload key, Google support can reset it, preventing you from losing the ability to update your app.
Step 4: Upload and Release
Navigate to Testing > Internal testing or Production in the sidebar. Create a new release, upload your .aab file located at build/app/outputs/bundle/release/app-release.aab, write your release notes, and save the release.
Designing High-Converting Store Listing Screenshots and Descriptions
Compiling optimized flutter release builds is only half the battle. To drive organic downloads, your store listings must be meticulously designed to convert visitors into users. This process is known as App Store Optimization (ASO).
+-----------------------------------------------------------------+
| App Store Optimization |
+-----------------------------------------------------------------+
| |
v v
+------------------+ +------------------+
| Visual Assets | | Text Metadata |
| - App Icon | | - App Title |
| - Screenshots | | - Subtitle |
| - Promo Video | | - Description |
+------------------+ +------------------+
Visual Assets and Dimensions
Your app icon and screenshots are the first elements users see. They must be polished, professional, and clearly communicate your app's core value proposition.
- App Icon: Must be simple, recognizable, and free of small text.
- iOS: $1024 \times 1024$ px (PNG, no transparency).
- Android: $512 \times 512$ px (PNG, 32-bit, with alpha channel) + Adaptive Icon layers.
- Screenshots: Do not simply upload raw device screenshots. Use high-fidelity device mockups with bold, readable text overlays highlighting key features.
| Platform | Device Target | Required Dimensions | Format | | :--- | :--- | :--- | :--- | | iOS | 6.7" iPhone (15/14 Pro Max) | $1290 \times 2796$ px | PNG or JPEG | | iOS | 6.5" iPhone (11 Pro Max) | $1242 \times 2688$ px | PNG or JPEG | | iOS | 5.5" iPhone (8 Plus) | $1242 \times 2208$ px | PNG or JPEG | | iOS | 12.9" iPad Pro (6th Gen) | $2048 \times 2732$ px | PNG or JPEG | | Android | Phone | Min: 320px, Max: 3840px (16:9 ratio) | PNG or JPEG | | Android | 7-inch Tablet | Min: 320px, Max: 3840px (16:9 ratio) | PNG or JPEG | | Android | 10-inch Tablet | Min: 320px, Max: 3840px (16:9 ratio) | PNG or JPEG |
Crafting High-Converting Descriptions
Your text metadata must balance user persuasion with search engine optimization (SEO) algorithms.
- App Title (30 characters): Include your brand name and 1-2 high-value keywords (e.g., Vyrova: Secure Cloud Analytics).
- Subtitle / Short Description (30-80 characters): A concise, punchy call-to-action or value statement (e.g., Track real-time business metrics on the go).
- Long Description (4000 characters):
- The Hook: The first three lines are critical before the "Read More" fold. State the primary problem your app solves.
- Feature Bullet Points: Use clear, benefit-driven bullet points.
- Keyword Integration: Naturally integrate your target keywords throughout the description. Avoid keyword stuffing, which can lead to app rejection.
- Social Proof & Trust: Mention awards, press coverage, or user testimonials if available.
Looking for Premium Mobile App Developers?
We build high-performance, native-grade cross-platform apps using Flutter and React Native. Let's discuss your product goals.
Rollout Strategies: Phased Releases and Staged Rollouts
Deploying a major update or a new application to 100% of your user base instantly is a high-risk strategy. Even with rigorous QA, production environments introduce unpredictable variables, such as edge-case device configurations, network anomalies, and unexpected server loads. To mitigate this risk, both platforms offer controlled, incremental rollout mechanisms.
+-----------------------------------------------------------------+
| Production Release |
+-----------------------------------------------------------------+
|
v
+--------------------------------------+
| Incremental Rollout |
+--------------------------------------+
/ \
/ \
v v
+---------------------------+ +---------------------------+
| iOS Phased Release | | Android Staged Rollout |
| (Fixed 7-Day Schedule) | | (Custom Percentages) |
+---------------------------+ +---------------------------+
Day 1: 1% Day 1: 5%
Day 2: 2% Day 2: 10%
Day 3: 5% Day 3: 20%
Day 4: 10% Day 4: 50%
Day 5: 20% Day 5: 100%
Day 6: 50%
Day 7: 100%
iOS Phased Releases
When you submit an update to App Store Connect, you can opt to use a Phased Release. This distributes your update to users with automatic updates turned on over a fixed 7-day period:
- Day 1: 1% of users
- Day 2: 2% of users
- Day 3: 5% of users
- Day 4: 10% of users
- Day 5: 20% of users
- Day 6: 50% of users
- Day 7: 100% of users
Managing a Phased Release
If you detect a critical bug or a spike in crash rates on Day 2, you can pause the phased release at any time for up to 30 days. This prevents additional users from downloading the buggy update while your engineering team develops a hotfix. Once the hotfix is compiled, you can submit the new build to replace the paused release.
Android Staged Rollouts
Google Play offers a highly customizable Staged Rollout system. Unlike Apple's fixed schedule, you define the exact percentage of users who should receive the update at each stage (e.g., 1%, 5%, 20%, 50%, 100%).
To configure a staged rollout:
- In the Google Play Console, navigate to your production release.
- Under Rollout percentage, select your initial target (e.g.,
5%). - Click Save and Review release.
As your monitoring tools confirm stability, you can manually increase the percentage:
# Example of updating rollout percentage via Fastlane
google_play_track(
track: 'production',
rollout: '0.20' # Increase rollout to 20% of users
)Monitoring Production Stability
During a phased or staged rollout, your engineering team must actively monitor production telemetry. Key metrics to track include:
- Crash-Free User Rate: Maintain a target of $>99.9%$ crash-free users. Tools like Firebase Crashlytics or Sentry are essential for real-time monitoring.
- API Latency & Error Rates: Ensure your backend services are scaling gracefully to handle the influx of new client requests.
- App Store Reviews: Monitor user reviews for immediate feedback on UI regressions or critical flow blockages.
By adopting these incremental rollout strategies, you protect your brand reputation, ensure a stable user experience, and establish a highly professional, risk-mitigated deployment pipeline for your Flutter applications.
