Expo vs Bare React Native: Which Approach to Choose

Veld Systems||6 min read

Every React Native project starts with the same question: Expo or bare workflow? The answer used to be simpler. Expo was the easy path with significant limitations, and bare React Native was the flexible path with significant setup overhead. In 2025, the landscape has changed dramatically. Expo has evolved from a limited sandbox into a comprehensive development platform that covers the vast majority of use cases, and the "bare workflow" distinction has blurred as Expo modules work in any React Native project.

We have shipped production apps with both approaches. Our perspective, informed by dozens of mobile projects, is that Expo is now the right starting point for nearly every React Native application. But "nearly every" is not "every," and understanding where Expo falls short is just as important as understanding where it excels.

What Expo Actually Is in 2025

Expo is no longer just a "managed" wrapper around React Native. It is a collection of tools that work independently or together:

Expo CLI replaces the React Native CLI for project creation, development, and building. It is faster, more reliable, and handles the sharp edges (Xcode configuration, Gradle versions, CocoaPods) that make bare React Native setup frustrating.

Expo Modules are native modules (camera, file system, notifications, secure storage, haptics, sensors, and 50+ more) that work in both Expo and bare React Native projects. They are actively maintained, well documented, and follow consistent API patterns.

EAS (Expo Application Services) handles builds, submissions, and over the air updates. EAS Build compiles your app in the cloud, so you do not need a Mac to build iOS apps. EAS Submit pushes builds directly to the App Store and Google Play. EAS Update deploys JavaScript updates to production apps without going through app store review.

Expo Router brings file based routing (similar to Next.js) to React Native, with deep linking, type safe navigation, and universal support for web, iOS, and Android from the same codebase.

Config Plugins are the key innovation that eliminated most reasons to eject from Expo. A config plugin modifies the native iOS and Android projects at build time, letting you configure native settings, add entitlements, modify the Info.plist or AndroidManifest.xml, and integrate native SDKs without manually editing native code. Most third party libraries that previously required bare React Native now ship config plugins that work with Expo.

We discuss the broader React Native ecosystem in our React Native vs Flutter and React Native vs native comparisons.

Where Expo Excels

Development speed. Starting a new project with Expo takes minutes. `npx create-expo-app` gives you a working project with TypeScript, file based routing, and a development build system. With bare React Native, setting up a comparable development environment takes hours of configuring Metro, linking native dependencies, and troubleshooting Xcode and Android Studio.

Over the air updates. EAS Update lets you push JavaScript and asset changes to production apps instantly, bypassing app store review cycles. A critical bug fix that would take 1 to 7 days through App Store review goes live in minutes. This is one of the most impactful features for production apps. We have used it to ship emergency fixes on Friday afternoons instead of waiting for Monday's review queue.

Cloud builds. EAS Build compiles your app on Expo's servers. This means your development team does not need local Xcode or Android Studio installations for routine builds. It also means reproducible builds, since the build environment is consistent regardless of what is on each developer's laptop. For distributed teams, this eliminates an entire category of "it builds on my machine" problems.

Consistent module API. Expo modules follow the same patterns for permissions, error handling, and platform differences. `expo-camera`, `expo-location`, `expo-notifications`, and others work the same way across iOS and Android. With bare React Native, you often use community modules from different authors with different API conventions, different permission handling, and different levels of maintenance.

Where Bare React Native Still Wins

The cases for bare React Native have narrowed significantly, but they still exist:

Heavy native module development. If your app's core value proposition requires custom native code, such as a custom camera pipeline, hardware integration, or a proprietary audio/video processing engine, bare React Native gives you direct access to the native projects. Config plugins can handle many native configurations, but when you need to write Swift/Kotlin code that integrates deeply with the React Native bridge, having the native projects in your repository is more straightforward.

Brownfield integration. If you are adding React Native to an existing native iOS or Android app rather than building a new app from scratch, bare React Native is the established path. Expo is designed for greenfield projects where it controls the native project structure. Integrating Expo into an existing native app is possible but not the primary use case.

Specific native SDK requirements. Some enterprise SDKs (certain banking, healthcare, or DRM libraries) require manual native project modifications that config plugins cannot express. This is increasingly rare as config plugins become more capable, but it still occurs with niche SDKs.

Build system control. Teams with existing CI/CD pipelines built around Fastlane, custom Gradle configurations, or specific Xcode build settings may find bare React Native easier to integrate. EAS Build is excellent but it is a different system, and migrating existing build infrastructure takes effort.

The EAS Build Cost Consideration

EAS Build pricing matters for team budgets. The free tier gives you 30 builds per month on slower machines. The Production plan at $99 per month provides faster builds, priority queuing, and more concurrent builds. The Enterprise plan adds custom build environments and dedicated support.

With bare React Native, builds run on your own infrastructure (or your CI/CD service like GitHub Actions or CircleCI). If you already have CI/CD set up, the incremental cost of adding mobile builds is lower than an EAS subscription. However, maintaining the build environment (keeping Xcode updated, managing Android SDK versions, handling signing certificates) has its own cost in engineering time.

For teams without existing CI/CD or without Mac hardware for iOS builds, EAS Build is worth every dollar. It eliminates days of DevOps work setting up and maintaining mobile build pipelines.

Production Readiness

Both approaches produce the same output: a native iOS and Android app compiled from the same JavaScript codebase. There is no performance difference between an Expo app and a bare React Native app. Expo does not add a runtime layer or wrapper that affects performance. The JavaScript bundle runs on the same Hermes engine in both cases.

Apps built with Expo are in production at significant scale. The Expo modules are tested against React Native's release cycle and updated promptly when new React Native versions ship. For most teams, Expo's update cadence is actually faster than what you would achieve maintaining bare React Native dependencies yourself.

We have deployed Expo apps to both app stores for clients across multiple industries, and the submission process is identical to bare React Native. Apple and Google cannot tell the difference, and there is no technical disadvantage to using Expo in production.

Our Recommendation

Start with Expo unless you have a specific, documented reason not to. The development speed advantage is real and compounds over the lifetime of a project. Over the air updates alone justify the choice for any production application. The config plugin system has eliminated the vast majority of "eject" scenarios that plagued earlier Expo versions.

Choose bare React Native when you are integrating React Native into an existing native app (brownfield), when your core product requires deep custom native code that goes beyond what config plugins can express, or when you have existing build infrastructure that you do not want to migrate.

Even in the bare React Native case, use Expo modules wherever possible. They work in bare projects and provide better maintained, more consistent native module implementations than most community alternatives.

If you are planning a mobile application and want help choosing the right approach, get in touch. We cover the full spectrum of mobile development decisions in our mobile app cost guide and through our web and mobile apps service.

FeatureExpoBare React Native
Project SetupMinutes. npx create-expo-app gives you TypeScript, file based routing, and a working dev environment immediatelyHours. Requires configuring Metro, Xcode, Android Studio, CocoaPods, and Gradle. Each developer sets up their own environment
Over the Air UpdatesEAS Update pushes JavaScript changes to production instantly. Bug fixes go live in minutes instead of waiting 1 to 7 days for app store reviewRequires integrating a third party OTA solution like CodePush (now App Center, being retired) or building your own update mechanism
Build SystemEAS Build compiles in the cloud. No local Xcode or Android Studio needed for routine builds. Reproducible across the teamLocal builds or your own CI/CD pipeline. Requires Mac hardware for iOS. You manage Xcode versions, signing, and provisioning profiles
Native Module Access50+ Expo modules cover common needs. Config plugins handle most native configurations. Custom native code possible via expo-modules-apiDirect access to native iOS and Android projects. Write Swift, Kotlin, or Objective C directly. Maximum flexibility for custom native code
Third Party Library SupportMost popular libraries work with Expo via config plugins. Some niche enterprise SDKs may require bare workflow for manual native project modificationsAll React Native libraries work. No compatibility concerns. Direct native project access handles any SDK integration requirement
File Based RoutingExpo Router provides Next.js style file based routing with deep linking, type safety, and universal web plus mobile support built inReact Navigation is the standard. Powerful but requires manual route configuration. No file based routing unless you add a third party solution
Development ExperienceExpo Go for instant previewing on physical devices without building. Development builds for testing with native modules. Fast refresh works reliablyMust build and install the app on device or simulator for every native change. Fast refresh works for JS changes but native rebuilds are slow
Brownfield IntegrationDesigned for greenfield projects. Adding Expo to an existing native app is possible but not the primary use caseThe established path for adding React Native screens or features to an existing native iOS or Android application
Build CostFree tier: 30 builds per month. Production plan: $99 per month for faster builds and priority queuing. Enterprise plans availableNo platform cost. Builds run on your hardware or CI/CD service. Cost is engineering time to maintain build infrastructure
Community and EcosystemLarge and growing community. Expo team maintains modules, tools, and documentation. Active Discord and GitHub for supportBroader React Native community. More Stack Overflow answers and blog posts. But also more outdated information from pre Expo era

Why Expo

  • +Over the air updates via EAS Update let you push critical fixes to production in minutes instead of waiting for app store review
  • +Cloud builds eliminate the need for local Xcode and Android Studio, enabling distributed teams to build iOS apps without Mac hardware
  • +File based routing with Expo Router provides type safe navigation with deep linking and universal web plus mobile support
  • +50+ actively maintained native modules with consistent APIs across platforms reduce integration time and maintenance burden
  • +Config plugins handle native project modifications at build time, covering most use cases that previously required ejecting

Why Bare React Native

  • +Direct access to native iOS and Android projects provides maximum flexibility for custom Swift, Kotlin, and Objective C code
  • +No platform dependency for builds, your existing CI/CD pipeline handles compilation and signing without a subscription
  • +The established approach for brownfield integration, adding React Native to existing native applications
  • +Full control over every aspect of the native project, including build settings, entitlements, and SDK configurations
  • +No build queue wait times since everything compiles locally or on your own infrastructure

The Verdict

Our Honest Take

Start with Expo for any new React Native project. The development speed, over the air updates, and cloud builds provide compounding advantages that grow over the project lifetime. Choose bare React Native only for brownfield integration into existing native apps, projects requiring deep custom native code that config plugins cannot handle, or teams with established mobile CI/CD infrastructure they prefer to keep. Even in bare projects, use Expo modules for the best maintained native module implementations available.

Ready to Build?

Let us talk about your project

We take on 3-4 projects at a time. Get an honest assessment within 24 hours.