Expo Go is a fast playground with a fixed native surface. A development build is your own debug binary with expo-dev-client, carrying every native module your project installs - the environment production apps are actually built from.
# Still prototyping with only Expo SDK modules? Expo Go is enough:npx expo start# Scan QR with Expo Go (simulator/emulator or device with matching SDK)# Need custom native code? Add the dev client and create a development build:npx expo install expo-dev-clienteas build --profile development --platform ios# Install the .ipa/.apk, then:npx expo start --dev-client
When to reach for this:
Deciding whether day-one Expo Go is sufficient for your SDK 57 spike.
Hitting Native module cannot be null after npm installing a library not bundled in Expo Go.
Testing push notifications, app/universal links, or custom splash/icon behavior realistically.
Onboarding teammates who confuse Expo Go limitations with Expo platform limitations.
# 2. Build and install (simulator example)eas build --profile development --platform ios# Download/install the build, then start Metro for dev-client:npx expo start --dev-client
New native module, icon, entitlements, SDK upgrade
JavaScript bundle
Metro output from npx expo start
Every Fast Refresh / reload
Your JS can only call native APIs that exist in the installed native app. Installing react-native-foo adds JS stubs to node_modules, but until the native code is compiled into your binary, calls fail at runtime.
import * as Expo from "expo";export function RuntimeBanner() { if (Expo.isRunningInExpoGo()) { return <Text>Expo Go - some native features disabled</Text>; } return <Text>Development / production native binary</Text>;}
Use runtime detection only for diagnostics - do not fork product logic permanently on isRunningInExpoGo() unless the feature is genuinely unavailable.
Installing a native library and expecting Expo Go to work - JS installs succeed but native calls throw. Fix:npx expo install expo-dev-client and create a development build.
Testing push notifications in Expo Go - Remote push requires your certificates in your binary. Fix: Development build with configured push credentials.
Assuming splash/icon changes appear in Expo Go - Expo Go shows its own shell; your branding ships with native builds. Fix: Validate assets in a development or preview build.
Forgetting --dev-client flag - Metro defaults to Expo Go QR flow; your custom binary won't connect correctly. Fix:npx expo start --dev-client after installing a dev build.
iOS device stuck on wrong SDK Expo Go - App Store only offers the latest Expo Go. Fix: Development build, or use simulator with a downloadable Expo Go build from expo.dev/go.
Rebuilding for every JS change - Unnecessary. Native rebuilds are only for native dependency or config plugin changes. Fix: Keep Metro running; reload JS for component edits.
Shipping expo-dev-client to production stores - Dev client belongs in debug/internal profiles. Fix: Separate development and production EAS profiles; production omits dev-client launcher UI.
Expo Go is a prebuilt Expo playground app from the app stores. It loads your JavaScript bundle over the network so you can preview UI quickly without compiling native code yourself.
What is a development build?
A development build is a debug version of your app with the expo-dev-client library installed. It includes your native dependencies and connects to Metro for JavaScript hot reload - the same architecture production uses, minus release optimizations.
When is Expo Go enough?
When you only use native modules already bundled inside Expo Go (most expo-* SDK packages), you are learning RN, or you are building UI that does not depend on custom native code, push, or app links.
When must I switch to a development build?
Before integrating libraries with native code outside Expo Go's bundle, testing remote push, configuring universal/app links, or validating real icons, splash screens, and entitlements.
What does expo-dev-client add?
A development launcher, switchable Metro URLs, network inspection, and support for loading your custom native module graph - capabilities Expo Go cannot replicate because its native binary is fixed.
How do I create a development build on EAS?
npx expo install expo-dev-clienteas build --profile development --platform ios
Set "developmentClient": true in the EAS profile. Install the artifact, then run npx expo start --dev-client.
Do I need to rebuild for every code change?
No. JavaScript and React changes hot-reload through Metro in both Expo Go and development builds. Rebuild when you add/remove native modules or change native config plugins.
Gotcha: Why does my new native package work on npm install but crash at runtime?
npm install adds JavaScript and native source to node_modules, but Expo Go's binary does not include that native code. Create a development build so the native module is compiled into your app.
Can I use Expo Go with SDK 57?
Yes on simulators/emulators and Android devices when Expo Go versions align. iOS physical devices must use the App Store Expo Go version compatible with SDK 57 - if mismatched, use a development build.
What command starts Metro for a development build?
npx expo start --dev-client
Without --dev-client, the CLI optimizes for Expo Go QR codes.
How do I detect Expo Go at runtime?
import * as Expo from "expo";Expo.isRunningInExpoGo(); // boolean
Use for diagnostics, not as a permanent feature flag strategy.
Are development builds the same as production builds?
They share native modules and config plugins, but development builds include dev-client tooling, debug symbols, and internal distribution. Production profiles strip dev-only code and apply release signing.
Can I test deep links in Expo Go?
Custom URL schemes partially work, but App Links / Universal Links need two-way association baked into your native binary - impossible in Expo Go. Use a development build.
What is the daily workflow after I have a dev build installed?
Start Metro once (npx expo start --dev-client), open the dev client app, pick your server, iterate on JS with Fast Refresh. Rebuild native only when native dependencies change.
Does expo-dev-client ship to the App Store?
No. Keep it in development/internal profiles. Production store builds use a production EAS profile without the dev launcher.