E-NO
React Native production 7 Min Read

React Native Production Operations Checklist with Practical Examples

calendar_today Published: 2026-07-26
update Last Updated: 2026-08-06
analytics SEO Efficiency: 97%
Technical guide illustration for React Native Production Operations Checklist with Practical Examples.

Intro

Production is a different game than development. This checklist gives you a practical, field-tested path to harden a React Native app for release, secure data and payments, add monitoring, improve performance, plan releases, and recover from incidents across Android, iOS, and Expo.

Workflow Overview

Use a simple, explicit flow to reduce rework and surprises:

  1. Plan: define target devices, OS versions, and success metrics (crash-free sessions > 99.5%, cold start p50 < 2s, API error rate < 0.5%, payment success rate > 99%).
  2. Configure: set release flags (Hermes, minification, resource shrinking, inline requires), versioning, and environment separation.
  3. Secure: protect secrets, lock network transport, and review permissions.
  4. Instrument: crash reporting, JS error handlers, performance and business metrics.
  5. Test: smoke tests on low-end and high-end devices; payment sandbox; offline and flaky network.
  6. Release gradually: internal testers, staged rollouts, watch dashboards.
  7. Operate: monitor, on-call ownership, backups, and regular upgrades.

Configuration and Build Flags

Harden release builds on both platforms.

  • General
  • Set proper app ID/bundle ID (e.g., com.company.appname) and semver (e.g., 1.7.0) with incrementing build numbers per store upload.
  • Disable debug-only libraries and logs in release.
  • Separate endpoints and keys for dev, staging, and production using app.config.js or .env files per environment.
  • Metro config: speed up startup by deferring requires
// metro.config.js
module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: { inlineRequires: true }
    })
  }
};
  • Android (Gradle)
  • Enable Hermes and R8, shrink resources, split ABIs to reduce APK size.
// android/app/build.gradle
project.ext.react = [ enableHermes: true ]
android {
  buildTypes {
    release {
      minifyEnabled true
      shrinkResources true
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
  splits {
    abi { enable true; reset(); include 'armeabi-v7a','arm64-v8a','x86_64'; universalApk false }
  }
}
  • Strip logs in release via Babel plugin:
// babel.config.js
plugins: [
  ['transform-remove-console', { exclude: ['error', 'warn'] }]
]
  • Set network security config; avoid cleartext unless required and scoped. Example res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="false">
    <domain includeSubdomains="true">api.example.com</domain>
  </domain-config>
</network-security-config>
  • Configure Play App Signing and secure keystores.
  • iOS (Xcode)
  • Enable Hermes in Podfile if using Hermes, set Release flags (dead code stripping, bitcode off for current toolchains, optimization level -Os).
  • Enforce ATS (HTTPS) with exceptions only if absolutely required and documented in Info.plist.
  • Configure correct provisioning and signing for Release.

Secrets and Security

  • Never embed long-lived secrets in the app. Keep private keys on the server.
  • Store access tokens in platform secure storage:
  • iOS: Keychain (restrict access group and accessibility level as needed, e.g., kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly).
  • Android: EncryptedSharedPreferences or Keystore-backed storage.
  • Avoid storing secrets in AsyncStorage.
  • Payments
  • Stripe: keep publishable key in app, but create ephemeral keys server-side. Do not store customer secrets on-device.
  • Google Play Billing: validate purchases on a secure server; do not trust client-only checks.
  • Permissions: request only what you need; provide in-app rationale; handle denial gracefully.
  • Transport: enforce HTTPS/TLS, pin domains if you control the backend; set sane timeouts (e.g., 10s connect, 30s read).

Monitoring and Crash Reporting

  • Add a crash reporter (native + JS) and performance monitoring (e.g., Sentry, Datadog, Bugsnag).
  • Initialize early in app startup and include release, build number, device, and user ID or session ID (respect privacy and consent).
  • Capture unhandled JS errors and rejections:
import { setJSExceptionHandler, setNativeExceptionHandler } from 'react-native-exception-handler';

setJSExceptionHandler((e, isFatal) => {
  // send to your crash service
  Sentry.captureException(e);
}, true);

setNativeExceptionHandler(errorString => {
  // send native crash info
  Sentry.captureMessage(errorString);
});
  • Track: app start time (cold/warm), UI freezes (> 16ms frame drops), network failures, payment flow outcomes, and screen transition timings.
  • Alerts: set thresholds for crash-free sessions (< 99.5%), error spikes (> 5% in 5 min), payment drop-offs (> 2% deviation).

Performance and Startup

  • Use Hermes for faster startup and lower memory (typically 20-30% faster TTI on low-end devices).
  • Enable inlineRequires and lazy-load heavy screens and modules.
  • Avoid expensive work on startup; defer analytics and non-critical fetches until after first paint.
  • Optimize images: WebP/AVIF where supported, correct sizes, caching via cache: 'force-cache' headers.
  • Use FlatList/SectionList with keyExtractor, getItemLayout when possible; avoid re-render storms (memoize props, useCallback/useMemo appropriately).

Networking and API Resilience

  • Set timeouts and retries with exponential backoff and jitter.
import axios from 'axios';

const api = axios.create({ baseURL: 'https://api.example.com', timeout: 10000 });

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const shouldRetry = (error) => !error.response || error.response.status >= 500;

api.interceptors.response.use(undefined, async (error) => {
  const cfg = error.config;
  cfg.__retryCount = cfg.__retryCount || 0;
  if (cfg.__retryCount < 3 && shouldRetry(error)) {
    cfg.__retryCount++;
    const backoff = Math.min(1000 * 2 ** cfg.__retryCount, 8000);
    const jitter = Math.random() * 500;
    await delay(backoff + jitter);
    return api(cfg);
  }
  return Promise.reject(error);
});
  • Use idempotency keys for write operations (especially for payments).
  • Offline support: cache reads, queue writes, and reconcile on connectivity restore (use NetInfo to detect status).
  • Validate SSL and enforce ATS on iOS. Avoid cleartext traffic; if unavoidable, scope hosts and paths tightly.

Payments: Play Billing and Stripe

  • Google Play Billing (in-app purchases or subscriptions)
  • Use the latest BillingClient (v6+).
  • Handle purchase states: Purchased, Pending, and Unspecified. Show UI for pending (e.g., cash-based payments in some regions like OXXO in Mexico or Boleto in Brazil).
  • Always acknowledge purchases within 3 days (consumables) or before granting entitlement (subscriptions).
  • Verify purchase tokens server-side against Play Developer API.
  • Support subscription upgrades/downgrades and proration modes (IMMEDIATE_WITH_TIME_PRORATION, etc.).
  • Test with license test accounts and sandbox products.
  • Stripe (cards, wallets)
  • Prefer PaymentSheet for a secure, standardized flow.
  • Generate ephemeral keys on your server; never embed secret keys in the app.
  • Handle 3DS authentication, app switching, and Activity/UIViewController lifecycle.
  • Use idempotency keys for payment intents to avoid duplicates on retries.
  • Log payment attempt outcomes and correlate with backend logs.

Expo Considerations

  • Choose managed vs bare based on native needs.
  • EAS Build
  • Define build profiles for development, preview, and production.
  • Use runtime versions and channels for safe update segmentation.
  • Updates
  • Use OTA updates for small JS/asset fixes that comply with store policies.
  • Any native module or permission changes require a new store build.
  • Config
  • Keep app.json/app.config in sync with store metadata (icons, permissions, deep links, schemes).

Release Management: Android and iOS

  • Android
  • Use internal testing track for smoke tests, closed testing for broader QA, then staged rollout to production (e.g., 5%, 25%, 50%, 100%).
  • Enable Play App Signing and integrity protections.
  • Keep a rollback plan: halt rollout or roll back to a prior release within Play Console.
  • iOS
  • Use TestFlight for internal and external testers (up to 10k external).
  • Consider phased release for production (1-day, 7-day, 30-day options).
  • Provide compliance metadata and accurate permission descriptions in App Store Connect.
  • Versioning and metadata
  • Use semantic versioning for marketing version and increment build numbers per upload.
  • Maintain clear changelogs and update notes.

Data, Storage, and Backups

  • Classify data: credentials/tokens, user content, cached API data, analytics.
  • Store sensitive data in secure storage; never in plaintext files or AsyncStorage.
  • Migrations: version your schema for SQLite or key-value stores and test upgrades and downgrades.
  • Android backups
  • Control Auto Backup with a fullBackupContent XML to exclude sensitive paths (e.g., shared_prefs, databases, files/keys).
  • iOS backups
  • Mark files that should not be backed up with the NSURLIsExcludedFromBackupKey attribute when appropriate.
  • Keychain items may migrate across device restores; plan token invalidation accordingly (e.g., bind tokens to device ID or rotate on first launch after restore).
  • Backend coordination: ensure server-side backups, retention, and restore drills align with client expectations.

Maintenance and SLOs

  • Define targets
  • Crash-free sessions: > 99.5% (Google Play "Excellent" threshold).
  • Cold start p50 < 2s, p90 < 4s on median devices.
  • API error rate < 0.5%, payment success rate > 99%.
  • Reviews
  • Weekly monitoring review: crashes, ANRs, perf regressions.
  • Monthly dependency review: security advisories and compatibility (React Native, Gradle, Xcode, key libraries).
  • Access and keys
  • Rotate credentials and cleanup unused access quarterly.

Upgrades and OS Compatibility

  • Plan quarterly React Native and library upgrades; avoid large version jumps (e.g., 0.72 -> 0.74, not 0.70 -> 0.74).
  • Track Android Gradle Plugin, Kotlin, Java, Xcode, Swift, and iOS/Android SDK targets in a VERSIONS.md file.
  • Test on the latest OS betas ahead of public release; fix deprecations early (e.g., Android 14 foreground service types, iOS 17 privacy manifests).
  • Pin toolchain versions in gradle.properties and Package.swift/xcodeproj to reduce unexpected build breaks.

Incident Response and Rollbacks

  • Feature flags and remote kill switches (e.g., LaunchDarkly, Firebase Remote Config) to disable risky features without store updates.
  • OTA rollback strategy (where allowed) for JS-only fixes via Expo Updates or CodePush.
  • Store controls
  • Android: halt or roll back staged rollouts in Play Console.
  • iOS: remove from sale or submit expedited review for hotfixes when necessary.
  • Runbooks
  • Define steps for payment outage, API outage, and crash spike events.
  • Include contact points, log links, dashboards, and decision trees (e.g., "if crash-free sessions < 99% for 15 min -> alert on-call -> check Sentry -> if new release -> halt rollout\"}).

Local Pilot Plan

Start small so you can verify quickly and safely.

Scope

  • Enable Hermes and inlineRequires.
  • Add crash reporting and capture unhandled JS errors.
  • Wrap one critical API call with timeouts and backoff, plus idempotency for writes.

Verification

  • Measure cold start time on two devices (e.g., Pixel 6a and Pixel 8) and compare before/after.
  • Trigger a handled JS error to confirm reporting appears in dashboard within 60 seconds.
  • Simulate network failures (airplane mode, throttling) and confirm retries and user messaging.

Rollout

  • Ship to an internal test track (Android) or TestFlight (iOS) with 10-20 testers.
  • Success criteria: no new crashes from pilot changes, p50 cold start improved > 10%, and API error handling verified.

Conclusion

A reliable release comes from repeatable operations: hardened builds, secured secrets, robust monitoring, tuned performance, resilient networking, careful payments handling, and disciplined releases. Start with a narrow pilot, verify improvements, then expand coverage to the rest of the app. Keep upgrades and maintenance on a predictable cadence, and practice rollback paths before you need them.

Related Research

Article Quality Score

Reader usefulness 97%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL