Expo or bare React Native? For a new mobile app, our starting recommendation is to evaluate Expo with a development build, then prove the hardest native integration. For an existing app, start by understanding its current iOS and Android projects before changing the workflow. The right decision should make the next release and the next year of maintenance easier to manage.
React Native is the foundation we use most for mobile development at MUBBITS, including Expo and bare workflows. This guide explains the choices we help clients work through: custom SDKs, native project ownership, build services, updates, migrations and cost. It is written for founders planning an app and engineering teams taking responsibility for one.
There is no useful universal winner. A coaching app with subscriptions, a content app with background audio and a field tool connected to specialist hardware can share many screens while presenting very different engineering risks. Those risks should lead the discussion.
Key takeaways
- Expo builds on React Native. The comparison is mainly about development tools and responsibility for the native projects.
- Expo Go and a development build are different environments. A limitation in Expo Go does not establish a limitation in your production app.
- Bare React Native projects can adopt Expo tools incrementally. A complete migration is a separate decision.
- Choose using a real integration, a release plan and a maintenance owner. Avoid promises of automatic performance gains or fixed development savings.
What do Expo and bare React Native actually mean?
React Native provides the foundation for building native applications with React. Expo adds a framework, libraries and development tooling around that foundation. React Native’s own getting-started documentation recommends a framework such as Expo for new applications, while also supporting development without one.
In this guide, bare React Native means a project where the team directly maintains the iOS and Android projects. That phrase describes responsibility for native files, not a separate rendering engine. It also does not describe two independent apps written entirely in Swift and Kotlin. A bare app can still share its React Native interface and application logic.
The practical distinction is what happens when the native setup changes. Who owns it? Where is the change recorded? Can another developer reproduce it? Answering those questions is more valuable than choosing a label based on an old comparison chart.
Expo vs bare React Native at a glance
This comparison describes Expo with development builds and generated native projects alongside a directly maintained native workflow. Teams can combine tools from both columns. Use the table to decide what to investigate, then validate the proposed setup with your actual dependencies.
| Decision | Expo with generated native projects | Bare React Native |
|---|---|---|
| Native configuration | Express repeatable setup in app configuration and plugins. | Maintain changes directly in the iOS and Android projects. |
| Custom native code | Include it in your development and production builds; check how configuration is reproduced. | Integrate it into the maintained native projects and document the setup. |
| Build infrastructure | Choose hosted builds or a local build pipeline. | Keep your pipeline or adopt selected Expo build tools. |
| New product | A useful starting point to evaluate against the required SDKs. | Consider when specific native constraints favour direct project ownership. |
| Existing product | Assess native customisations before adopting generation. | Keep a working setup while reviewing targeted improvements. |
| Main planning question | Can the team reproduce and maintain the required configuration? | Can the team maintain native project changes and upgrades reliably? |
Expo Go is not the same as an Expo development build
Expo Go is a prebuilt app with a fixed set of native libraries. It is convenient for learning and trying compatible features. A development build is a debug version of your own application with the native libraries and configuration your project needs. Expo recommends development builds for production projects.
That difference matters when evaluating an SDK. A package may fail inside Expo Go because its native code is absent from that installed app. Before rejecting Expo, establish whether it works in a development build with the proper configuration. Installing another JavaScript package alone cannot add native code to an already installed binary.
For a project review, ask to see the actual application installed on a device. Check its identity, sign-in redirect, permission prompts and the required integration. A convincing demonstration should exercise the same capability the customer will depend on. Keep a short record of what was tested so a successful prototype does not become an assumption about every other feature.
When Expo is a strong starting point
For a new app with accounts, content, notifications, subscriptions and ordinary device integrations, we would usually investigate Expo first. This is our evaluation approach, not a claim that every package or requirement will fit automatically. A consistent setup can make it easier for a team to review working features and keep development moving while the product takes shape.
The choice is especially worth exploring when the app has no existing native configuration to preserve. Start with one complete journey: sign in, load real data, perform the main action and recover from a failed request. Add the highest-risk integration early. This gives the team something more useful to assess than a collection of polished but disconnected screens.
We would also ask who will take over after launch. The first team may know the project well, but the next engineer needs a reproducible build and an understandable structure. A workflow is valuable when it makes that handover easier. If it requires undocumented exceptions that only one developer understands, investigate those exceptions before treating the setup as a long-term advantage.
When maintaining bare React Native makes sense
An established app may have native integrations, build variants or a release process that already works well. Replacing that arrangement solely to adopt a preferred tool can create work without improving the customer experience. Direct ownership of the native projects can also be appropriate when the team needs to make frequent specialised platform changes and can maintain them confidently.
We would examine the changes themselves. Are they small settings that can be reproduced automatically, or do they involve substantial native application code? Is there a vendor SDK with unusual build requirements? Is React Native embedded inside a larger native product? The answer should describe the concrete constraint rather than rely on the vague phrase full control.
For an inherited app, a useful first milestone is reproducing its current release from a clean checkout. Record the toolchain, dependencies, configuration and signing responsibilities. Resolve immediate build or release problems before proposing a larger transition. A smaller improvement that removes a repeated failure may be more valuable than a migration that leaves the business waiting for its next feature.
Test native integrations before committing to the workflow
Expo supports libraries containing native code and custom modules. A development build can include those capabilities; the team still needs to install, configure and rebuild the app correctly. The Expo Modules API is one option for implementing native functionality in Swift and Kotlin. Whether a particular integration is suitable remains a project-level question.
Create a short inventory of essential SDKs: subscriptions, authentication, analytics, media, maps, Bluetooth or any hardware connection. For each dependency, record the supported platforms, maintenance status, required configuration and fallback if the integration fails. Check the exact versions together. A package being available does not prove that the full combination builds or behaves correctly.
For an audio product, test interruption and resumption. For a device-connected tool, test connection loss and recovery. For a subscription product, test restored access and changed account state. These examples describe acceptance tests to plan, not a promise that a library supplies the whole feature.
A focused prototype should answer one risky question and leave a useful result: a working integration, a known limitation or a clear reason to choose another approach. That evidence is a better basis for estimating the product than a generic Expo-versus-bare score.
Prebuild and CNG: where should native changes live?
Continuous Native Generation, or CNG, generates native projects from declared inputs. Expo Prebuild is the tool that creates the iOS and Android directories in that workflow. Configuration plugins can apply native setup during generation. The important boundary is the source of truth: changes that must survive regeneration need to be expressed in the maintained inputs.
Direct edits inside generated directories can disappear when those directories are recreated. In particular, the clean Prebuild option deletes and regenerates the native projects. Do not run it casually on an inherited app with unrecorded customisations. First identify what must be preserved, put the current work under version control and establish how each change will be reproduced.
A practical handover should explain whether the native directories are generated or maintained directly, where custom code lives and which command produces a release candidate. Avoid a mixed arrangement where some engineers assume a native edit is permanent while others regenerate the project. The team needs one clear maintenance policy.
Build services, store releases and account ownership
EAS Build is a hosted service that can produce app binaries for Expo and React Native projects. It can help with build profiles, distribution and signing workflows. Choosing Expo does not require choosing hosted builds; local compilation is also possible with the necessary platform toolchain. Decide where builds run separately from deciding how the app is written.
For a client product, ownership needs to be clear from the beginning. Identify who controls the repository, developer accounts, signing assets, backend, build service and production configuration. A successful handover means the client or their authorised team can continue releasing the app. It should not depend on an agency employee’s personal account.
Separate development, preview and production environments. Review the backend URL, app identifier and enabled integrations in a release candidate before it reaches users. Testers should know which environment they are using and how to report a problem.
Plan for store feedback as well as the technical build. Compiling successfully does not guarantee approval or a specific review date. Assign someone to coordinate the submission, product information and any required changes so the release has a clear owner.
Over-the-air updates still have a native boundary
An over-the-air update can deliver compatible JavaScript and assets to an installed app. It cannot insert a new native library into that app’s existing binary. Expo’s runtime-version mechanism identifies which native runtime an update is compatible with; a native change requires a new build and appropriate distribution.
That distinction belongs in the release plan. A copy adjustment and a new device SDK are different kinds of change. Before publishing, confirm which installed versions can run the update and whether the preview build matches the intended runtime. Define a gradual rollout and recovery process appropriate to the product.
Consider a hypothetical app adding a new camera capability. If the installed binary does not contain the required native code, sending interface code that calls it is not enough. The release must include the native build first, with compatibility tracked correctly.
We would document update channels, access permissions and who can promote a change. Remote delivery still needs testing and must respect the relevant platform policies. It is an operational capability, not permission to skip release review within the team.
Compare total cost and measured performance
There is no reliable universal percentage by which Expo is cheaper or bare React Native is faster. A useful estimate starts with the product: screens, data, native integrations, backend work, administrative tools, testing and maintenance. Then identify which workflow changes the effort required for those tasks.
Ask for separate estimates for the first release and ongoing ownership. The latter should account for dependency updates, operating-system changes, build maintenance, monitoring and support. Hosted services may introduce usage costs; a self-managed pipeline introduces infrastructure and maintenance work. Compare current plans against expected use instead of assuming that one route is free to operate.
Performance deserves the same specificity. Choose a demanding screen and a representative device. Measure launch, scrolling, media behaviour or synchronisation according to the app’s actual purpose. Use production-like builds and data. A slow API, unnecessarily large image or expensive render cycle will not be explained by the word Expo alone.
Set acceptance criteria before comparing options. If an app meets its users’ needs in either workflow, maintainability may decide the choice. If a particular interaction misses the target, investigate that interaction before proposing a rewrite. A measured fix is easier to justify than a framework change based on a general reputation.
Moving an existing app toward Expo without a blind rewrite
Expo tools can be adopted in an existing React Native application in stages. Installing compatible modules, improving the development environment, using a build service and adopting generated native projects are separate changes. You do not need to treat them as one all-or-nothing migration.
Start with a working baseline and a dependency inventory. Record the current app identifiers, release configuration and important user journeys. Identify native customisations before deciding whether generation is suitable. A move to CNG requires a plan for reproducing those customisations; using selected Expo tools does not itself require that move.
Our proposed migration checklist would include authentication, deep links, notifications, media, offline data and any paid access that the product uses. Compare the new build with the baseline on both platforms. Preserve the existing product identity and user data unless a change is explicitly part of the agreed scope.
Define a rollback point before the first production release. Separate migration work from unrelated product changes where possible so failures are easier to diagnose. If the review shows little benefit, keep the existing workflow and fix the specific maintenance problem instead.
A subscription app needs more than a framework decision
Coach Phil is an example of the wider product scope MUBBITS delivers. A fitness instructor and influencer needed a personal subscription app for client goals, meals and exercises. We built the client mobile app and the administration workspace used to manage the coaching service. The case study shows both sides of that product.
For a similar brief, the choice between Expo and directly maintained native projects is one decision within a larger plan. Someone must publish workouts, update meals, assign goals and support members. The app must show the right content and access state when those records change. A polished home screen alone does not complete the service.
Before estimating a coaching product, we would map the member journey alongside the coach’s workflow. What can members access? Which content is shared and which is assigned? What happens when a subscription changes or a user signs in on another device? How does support investigate an issue?
These questions help identify what the mobile app, backend and admin panel each need to do. They also reveal the integrations worth testing early. Use a case study to assess the team’s product experience; use a technical review to establish which workflow fits your own app.
What to bring to a React Native development conversation
You do not need to arrive with Expo or bare React Native already selected. Bring the audience, the main task the app should solve, the platforms it needs to support and the integrations that cannot be removed from scope. If a product already exists, share its repository and build information through the agreed access process.
A useful first engagement can be a focused review, a prototype of the difficult integration or a delivery plan for a defined release. Agree what evidence the work should produce. The result should explain the recommended workflow, unresolved dependencies and the next step clearly enough for the product owner to make a decision.
MUBBITS works across React Native, Expo and bare workflows, together with product design, backend integration, administration and release support. Our mobile development service explains that scope. Tell us where the app is today and what needs to work next; we can help shape a practical starting point.
- A short description of the users and the complete journey for the first release.
- Must-have native SDKs, device features and supported iOS and Android devices.
- Existing designs, code, backend services and known build or release issues.
- Who owns production accounts and who will maintain the app after launch.
- The decision you need from the review and the constraints it must respect.
Frequently asked questions
Is Expo different from React Native?
Expo is a framework and set of tools built around React Native. Choosing Expo does not mean abandoning React Native. For this comparison, the main issue is how the team configures and maintains the native projects and which development tools it adopts.
Can a production Expo app use custom native code?
Yes. A development build can include the app’s required native libraries and custom code. Expo Go has a fixed native runtime, so it cannot test every integration. Confirm the package, configuration and build requirements for the specific SDK rather than treating an Expo Go limitation as the final answer.
Does bare React Native automatically perform better?
No. Compare the actual implementation in production-like builds on representative devices. Rendering work, native modules, media, networking and data handling can all affect the experience. Workflow ownership alone is not a meaningful performance benchmark.
Do we have to use EAS Build if we choose Expo?
No. Hosted builds are an option; local builds are also possible with the required native tooling. Compare the team’s access, infrastructure, signing responsibilities and maintenance capacity before choosing the build setup. Bare projects can use selected Expo services too.
Can we move a bare app to Expo without rebuilding every screen?
Potentially. Expo tools can be adopted incrementally in an existing React Native app. The effort depends on its dependencies and native customisations. Review the current build first, and treat moving to generated native projects as a separate migration with its own verification.
Can MUBBITS take over an existing Expo or bare React Native app?
Yes. We can review the codebase, reproduce the build and agree a scope for improvements, integrations or the next release. We need a clear view of current issues and ownership of the backend, developer accounts and signing setup. A review helps establish whether the existing workflow should continue or change.
Working through this in your product?
We can help you turn these decisions into a practical plan and working software.
Explore React Native and Expo app developmentTalk to the team
