What each one actually is
Expo Go is one app, published by Expo, that you install from the App Store or Play Store. It contains a React Native runtime plus a fixed, precompiled set of Expo SDK native modules. When you scan a QR code, it downloads your JavaScript bundle and runs it against those modules. Your project never gets compiled — which is exactly why it starts in seconds, and exactly why it cannot run native code Expo did not anticipate.
A development build is the same idea with the binary swapped for yours. You add expo-dev-client, build once, and install the result on your device. It still connects to Metro, still hot-reloads, still has a dev menu — but the native side is compiled from your project, so every dependency and config plugin you declared is really in there.
The mental model that helps: Expo Go is someone else’s app running your JavaScript. A development build is your app, in development mode.
Side by side
| Capability | Expo Go | Development build |
|---|---|---|
| Time to first run | Seconds — scan a QR code | One cloud or local build (5–20 min) |
| Hot reload | ✅ | ✅ Identical |
| Expo SDK modules | ✅ The set Expo bundled | ✅ Any of them |
| Third-party native libraries | ❌ | ✅ |
| Config plugins that touch native files | ❌ | ✅ |
| Custom bundle ID / icon / splash on device | ❌ Shows as Expo Go | ✅ Your app |
| Remote push notifications (Android) | ❌ Removed in SDK 53 | ✅ |
| Native debugging in Xcode / Android Studio | ❌ | ✅ |
| Share with a non-technical tester | ⚠️ They install Expo Go first | ✅ Internal distribution link |
| Rebuild needed when JS changes | No | No |
| Rebuild needed when native deps change | N/A | Yes |
The five triggers that end Expo Go
- A native dependency. Payments, health data, Bluetooth, maps with a vendor SDK, a native video player, most analytics SDKs. If the package ships iOS or Android source, Expo Go cannot load it.
- A config plugin. Anything that edits
Info.plist, the Android manifest, entitlements, or build settings. Expo Go runs a binary that was compiled before your plugin existed. - Android push notifications. Remote push in Expo Go on Android was removed in SDK 53. If notifications are core to your product, you need a development build from day one.
- Real testers. Handing a beta to someone who has to install Expo Go, make an account, and scan a code loses you most of the testers. Internal distribution of a development build is a link and an install.
- Anything identity-shaped. Custom bundle identifier, app icon, deep-link scheme, associated domains. In Expo Go the app on the home screen is Expo Go, so none of it is testable — including deep links.
Making the switch
It is a one-time cost of about twenty minutes, most of which is a build queue:
npx expo install expo-dev-client
# eas.json → add a development profile:
# "development": {
# "developmentClient": true,
# "distribution": "internal"
# }
npx eas build --profile development --platform ios
# or build locally, no EAS account needed:
npx expo run:ios
npx expo start # opens in your dev build, not Expo GoAfter that, day-to-day work is identical to Expo Go. You only rebuild when the native layer changes, which is rarer than people expect — adding a screen, changing state management, restyling everything, and rewriting your API layer are all pure JavaScript.
One habit worth adopting: rebuild the development client deliberately, right after adding a native dependency, rather than the next time something breaks. Half of “Expo is flaky” complaints are a stale dev client running new JavaScript.
So which should you use?
Use Expo Go for the first few days of a project, for learning, and for throwaway prototypes where the entire app is Expo SDK modules and JavaScript.
Use a development build for anything you intend to ship. If you already know the app will take payments or send notifications, skip Expo Go entirely — the twenty minutes you save is repaid with interest the first time you debug a phantom crash.
Skipping the setup entirely
If you would rather not hand-configure any of this, ShipNative generates a complete Expo project from a description, runs it live on your phone while you iterate, and exports the source with EAS configuration already in place — so the first time you touch eas.json is when you want to change something, not to get started.