Mahbubul Alam.
AI & Mobile

Shipping React Native Apps: Fastlane, CodePush, and the App Store Grind

Jul 20263 min read
Shipping React Native Apps: Fastlane, CodePush, and the App Store Grind

The gap between "it runs" and "it's released"

A React Native app running in Expo Go on your development machine is maybe 60% of the work. The remaining 40% — code signing, provisioning profiles, store metadata, screenshot generation per device size, staged rollouts, and the actual review process on both stores — is where release day either goes smoothly or turns into an afternoon of certificate errors. Automating this pipeline properly is what turns "ship a mobile app" from an occasional, dreaded event into a routine one.

Fastlane as the automation backbone

# Fastfile — one command, both platforms
lane :release do
  increment_build_number
  build_app(scheme: "MyApp")
  upload_to_app_store(skip_screenshots: true, submit_for_review: true)

  build_android_app
  upload_to_play_store(track: "production")
end

Fastlane's real value isn't any single step — it's that the entire release process becomes one reproducible command instead of a checklist of manual steps in Xcode and Android Studio that a tired engineer will eventually get wrong at 11pm before a deadline. Certificate and provisioning profile management (via match) in particular removed an entire category of "works on my machine but not in CI" failures that used to eat a half day per release.

CodePush: shipping without waiting on Apple

App Store review can take anywhere from a few hours to several days. For anything that isn't a native code change — copy fixes, a broken API endpoint reference, a UI bug in JS-only code — CodePush pushes an update directly to installed apps, bypassing store review entirely. This is the difference between "we found a bug, we'll fix it in the next release cycle" and "we found a bug, it's fixed for users within the hour."

codePush.sync({
  updateDialog: false,
  installMode: codePush.InstallMode.ON_NEXT_RESUME,
});

The discipline that matters here is knowing what CodePush can and can't ship — any change touching native modules, permissions, or anything Apple's review guidelines consider a "significant" change still needs a full store release. Using CodePush for those anyway is a fast way to get an app pulled from the store for violating review terms.

Staged rollouts as a safety net

Both stores support percentage-based rollouts — release to 10% of users, watch crash reporting and key metrics for a day, then ramp to 50% and 100% if nothing's on fire. This caught a genuinely bad release once: a crash on a specific older Android OS version that hadn't shown up in any of our test devices, caught at the 10% stage instead of the full user base, because the crash rate spiked visibly in the rollout dashboard before most users ever saw it.

What actually made five apps sustainable

  • One shared Fastlane configuration pattern reused across apps, not reinvented per project
  • CodePush for the fast-follow fixes that don't need App Store review
  • Staged rollouts as a default, not an occasional precaution
  • Crash reporting (Sentry) wired in from the first release, not added after the first production crash

None of this is glamorous work, but it's the difference between a mobile release being a routine Tuesday afternoon task and an all-hands-on-deck event every single time.

#react-native#mobile#ci-cd