Build a Release Version
Produce a signed release build for iOS and Android, protect your keystore, and debug crashes that only happen in release.
This guide covers producing a signed release build of a React Native app for iOS and Android, and the differences from a debug build that commonly cause release-only bugs.
Quick Answer
Generate and carefully back up an Android signing keystore, configure release signing in Gradle, build with ./gradlew bundleRelease (for Play Store upload) or assembleRelease (for a standalone APK); archive and export from Xcode on iOS, or use eas build as a managed alternative to both.
1. Debug vs Release
Release builds strip debug tooling, enable JS minification, and (on Android) can run ProGuard/R8 code shrinking. Something that works in debug and breaks only in release is almost always one of: a missing ProGuard keep rule stripping a class that's used via reflection, or a debug-only environment variable/flag the release build doesn't have.
2. Android: Generate a Keystore
keytool -genkeypair -v -keystore release.keystore -alias release -keyalg RSA -keysize 2048 -validity 10000
Back this up somewhere durable and secure. If you lose it, you cannot publish updates to an existing Play Store listing under the same app; your only recovery path is Google Play App Signing's key reset process, which has real constraints and delays. Losing the keystore is one of the most damaging, avoidable mistakes in mobile release engineering.
3. Android: Configure Signing
Reference the keystore from android/app/build.gradle under signingConfigs.release, then build:
cd android
./gradlew bundleRelease # produces an .aab, required for new Play Store uploads
./gradlew assembleRelease # produces a standalone .apk
4. iOS: Archive and Export
In Xcode: Product → Archive, then use the Organizer to export or directly upload to App Store Connect. This requires valid release signing (a distribution certificate and provisioning profile) already configured.
5. EAS Build as a Managed Alternative
eas build --platform all builds both platforms in the cloud, managing signing credentials for you if you opt in, which avoids handling keystores and certificates locally.
Common Issues
App crashes in release but works fine in debug check for ProGuard/R8 stripping a class used via reflection (common with some native modules); add a -keep rule, or check for a debug-only config value the release build lacks.
Play Store rejects the upload, wants an .aab not an .apk new app submissions require an Android App Bundle; use bundleRelease, not assembleRelease, for store uploads.
Keystore lost for an already-published app, this is a serious problem; look into Google Play App Signing's key reset/upgrade process rather than assuming there's no path forward, but expect delay and friction.
iOS archive fails with a signing error the distribution certificate or provisioning profile is missing, expired, or doesn't match the bundle identifier.
Verification Checklist
- the Android keystore is generated and backed up somewhere durable, outside the project repo;
- release signing is configured in Gradle;
bundleReleasesucceeds and produces a valid.aab;- the release build has been manually tested, not just the debug build;
- iOS archiving succeeds with valid distribution signing.