Expo managed vs bare workflow: when to eject (and when not to)

by | Nov 6, 2026 | Tutorials | 0 comments

Expo’s managed workflow is the right default for most React Native products. It gives you a fast start, over-the-air updates, and a build service without asking you to maintain two native projects. The mistake is treating “managed” as a permanent architectural decision instead of a starting point.

Ejecting is not a badge of seriousness. It is a trade: you gain native control and lose upgrade convenience. The teams that do it well decide from concrete requirements, not frustration.

What the managed workflow gives you

  • Upgrade path: Expo SDK upgrades are usually a version bump plus a short list of API changes.
  • OTA updates: JavaScript changes can ship without a store review.
  • EAS Build and Submit: cloud builds, signing, and store delivery without maintaining local native toolchains.
  • Config plugins: many native changes can be expressed declaratively instead of editing Xcode and Gradle projects.
  • Smaller maintenance surface: fewer native files, fewer merge conflicts, fewer “works on my machine” build problems.

For a small team shipping a content, commerce, or workflow app, that is usually the correct trade.

What bare / prebuild actually changes

“Ejecting” now usually means moving to prebuild: Expo generates ios/ and android/ projects you own and can edit. You keep much of the Expo tooling, but native projects become part of your repository and your responsibility. From that point, every SDK upgrade can require merging native changes.

You gain direct access to native modules, custom build steps, platform APIs, and any third-party SDK that does not have a config plugin. You also take on signing, native dependency versions, and build reproducibility as first-class engineering work.

When ejecting is justified

1. A native module has no config plugin

If the SDK you need only ships native code and cannot be wired through a config plugin, prebuild is the honest path. Do not fake it with patches you cannot maintain.

2. You need a custom build step

Custom compilation, code generation, native binary stripping, or a build pipeline that EAS cannot express is a real reason to own the native projects.

3. You need deep platform control

Background execution, custom camera pipelines, Bluetooth, low-level networking, or platform-specific performance work may require native code that the managed runtime does not expose.

4. Compliance or a vendor SDK demands it

Some banking, healthcare, or enterprise SDKs require direct native integration. That is a requirement, not a preference.

When you should stay managed

  • You rely on OTA updates for fast fixes. Losing that is a product decision, not just a technical one.
  • Your integrations already have config plugins — use them before ejecting.
  • Your team is small and cannot absorb native upgrade work every SDK cycle.
  • You are still finding product-market fit. Optimize for iteration speed, not native purity.

A safe migration checklist

  1. Audit dependencies. List every native SDK and check for a config plugin before deciding.
  2. Try config plugins first. Many “we must eject” cases are solved by a plugin and a development build.
  3. Move to development builds. Test the real native runtime before changing the project shape.
  4. Run npx expo prebuild on a branch. Commit the generated projects and review the diff; do not generate them ad hoc.
  5. Pin your toolchain. Node, CocoaPods, Gradle, JDK, and EAS CLI versions belong in the repo.
  6. Set up EAS profiles for dev, staging, and production. Keep signing keys and channels separate.
  7. Test an SDK upgrade before you need it. The real cost of ejecting appears at the next upgrade, not on day one.
  8. Document rollback. A one-command rollback is part of the release process, not an afterthought.

Decision matrix

Requirement Managed Bare / prebuild
Standard auth, payments, analytics, push Yes Usually unnecessary
OTA updates and fast iteration Strong Weaker / custom
Native SDK without a config plugin Blocked Required
Custom native build pipeline Limited Full control
Small team, frequent SDK upgrades Better Higher maintenance

Bottom line

Stay managed until a named requirement forces you out. When that happens, eject deliberately: audit the native dependencies, prefer config plugins, test a development build, and budget for upgrade work. Ejecting is not a maturity milestone. It is a maintenance contract you sign with your future team.

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

avatart

About

I’m a System Administrator and a developer with 10+ years of experience.