---
title: "Expo vs Bare React Native for Production Apps"
canonical: https://zarki.tech/insights/expo-vs-bare-react-native
---

# Expo vs Bare React Native for Production Apps

Expo is no longer the training-wheels SDK. Here is when we stay on Expo for production, and when we eject to a bare React Native app with native projects in git.

By Antoine Khoury Abboud. Published 2026-09-04. Updated 2026-09-04.

The old advice was: prototype in Expo, eject before production. That advice is now usually wrong.

Expo in 2026 is a **production toolchain** — EAS Build, config plugins, a reasonably honest native layer — not a toy runtime. Bare React Native is still the right call. It is just no longer the default.

We make this choice on real apps, including [Flexa Fitness](/#work) and other React Native work in the [services](/#services) we sell. The criterion is not ideology. It is native surface area.

## Stay on Expo when

- you need OTA-friendly JS updates for a business app
- credentials, store submissions, and CI should be boring
- native modules you need already exist as config plugins or Expo modules
- the team should not be maintaining two Xcode/Gradle personalities by default

For trainer ops, bookings, dashboards, and most B2B mobile, this is the path. You get a single `app.json` / `app.config` as the source of truth instead of a folk ritual in `ios/`.

## Go bare (or a prebuild you fully own) when

- you need a native SDK that will not survive a config plugin
- you are already maintaining significant Swift/Kotlin
- the app *is* a camera, BLE, or background-location machine
- a vendor’s support contract says “send us the Xcode project”

“Bare” here means the native directories are yours. You can still use Expo modules. You just stopped pretending `ios/` is generated smoke.

## The trap: half-ejected

The worst place is an Expo app with a growing `plugins` array nobody understands, plus patches, plus a custom `expo prebuild` that only one person can run.

Rules we use:

- if a plugin would need to be written twice, consider owning the native project
- if you cannot explain a native change in the PR, it does not ship
- pin SDK versions like you pin anything else that can brick a store build

## Performance and “feel”

Users do not feel Expo. They feel navigation, lists, images, and the main thread. Those are React Native problems (and design problems). Moving to bare to “make it faster” without a profiler is theatre.

If you do have a hot path — mapping, camera, charts — isolate it in a native view. That isolation works on both Expo and bare.

## A practical default

Start Expo. Add the first uncomfortable native dependency deliberately. The day that dependency is the product, budget a controlled prebuild and treat native as code, not as a black box.

The previous fork in this series is [React Native vs native](/insights/react-native-vs-native-2026). If you are still choosing the platform, read that first.
