All articles
Mobile DevelopmentMay 24, 2026 7 min read

Expo Dev Client vs Expo Go in 2026: Stop Fighting Your Own Tooling

Expo Go is great until it isn't. Here's when to graduate to a custom dev client, what breaks during the switch, and how to keep your team productive while you migrate.

Expo Dev Client vs Expo Go in 2026: Stop Fighting Your Own Tooling

Every React Native team using Expo hits the same wall eventually: you want to add a library that needs native code, you open the docs, and Expo Go quietly stops being an option. Most teams panic, some eject prematurely, and a few discover the middle path — a custom dev client — six months too late.

This is the breakdown we wish someone had handed us the first time a client asked for Bluetooth, HealthKit, or a vendor SDK that ships its own .aar.

What Expo Go actually is (and isn't)

Expo Go is a pre-built sandbox app that Expo publishes to the App Store and Play Store. It bundles a fixed set of native modules — the Expo SDK — and runs your JavaScript on top. That's the entire trick. When you scan a QR code on a teammate's machine, you're loading their JS bundle into the same shared host.

This is brilliant for prototypes, classroom demos, and the first six weeks of almost any greenfield project. There's no Xcode, no Android Studio, no provisioning profiles. A designer can run the app on their iPhone in two minutes.

The ceiling shows up the moment you need any of the following:

  • A native module outside the Expo SDK (think: a specific payments SDK, an OEM-provided scanner library, MDM hooks)
  • A config plugin that modifies Info.plist or AndroidManifest.xml beyond what Expo Go already declares
  • Custom entitlements: associated domains, app groups, HealthKit, CarPlay
  • A different bundle identifier per environment (staging vs prod) so you can install both on one device

Expo Go can't help with any of those. It's not a limitation of Expo the framework — it's a limitation of running inside someone else's app shell.

What a custom dev client actually is

A dev client is your own app — your bundle ID, your icon, your native modules — built once and reused for every JS change after that. It still has the Expo developer menu, still hot reloads, still connects to Metro. It just happens to be an app you own rather than one Expo publishes.

You build it with EAS Build (or locally if you enjoy pain), install the resulting .ipa or .apk on your devices, and from then on your iteration loop looks almost identical to Expo Go. The difference: you can put whatever native code you want inside it.

The mental model shift

The thing that trips teams up is the separation between native build and JS bundle. With Expo Go they were always coupled in your head — one app, one experience. With a dev client:

  • The native binary changes only when you add or update native dependencies
  • The JS bundle changes every time you save a file
  • Most days, nobody rebuilds the binary at all

In our experience, a healthy team rebuilds the dev client maybe once every two or three weeks. The rest of the time, new engineers install the existing build from an internal distribution link and start hacking on JS the same afternoon.

When to switch — and when not to

Stay on Expo Go if all of these are true:

  • You're prototyping or in the first month of a project
  • Your dependencies are all inside the Expo SDK
  • You don't need separate staging and production installs on the same device
  • Your client demo audience is technical enough to install Expo Go themselves

Switch to a dev client when any of these become true:

  • A product requirement forces a native module Expo Go doesn't ship
  • You need TestFlight or internal Play tracks for non-technical stakeholders
  • You want to enforce code signing, certificate pinning, or proguard rules
  • Your CI is producing release builds and you want dev and release to share the same native foundation

The mistake we see most often is teams flipping the switch too late, usually the week before a milestone, then losing four days to a build environment they've never touched.

The migration, step by step

Assume you already have an Expo project that runs in Expo Go. Here's the path we use.

1. Install the dev client package

npx expo install expo-dev-client

That's it for the JS side. The package wires up the dev menu and the launcher screen you'll see when you open the app without Metro running.

2. Configure EAS

If you haven't already:

npm install -g eas-cli
eas login
eas build:configure

This creates eas.json. Add a development profile that produces a debuggable build with the dev client baked in:

{
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "ios": { "simulator": false },
      "android": { "buildType": "apk" }
    },
    "preview": {
      "distribution": "internal",
      "channel": "preview"
    },
    "production": {
      "channel": "production"
    }
  }
}

A second development-sim profile with "simulator": true is worth adding so engineers on Macs can run the iOS dev client without a physical device.

3. First build

eas build --profile development --platform ios
eas build --profile development --platform android

The first iOS build will ask about credentials. Let EAS manage them unless your client has strict signing policies — then you'll upload your own .p12 and provisioning profile. Android is more forgiving; EAS will generate a keystore if you don't have one, and you should download it and store it somewhere safe immediately.

4. Distribute

For internal distribution, EAS gives you a QR code and install URL. On iOS, devices need to be registered with your Apple Developer account (UDIDs added to the provisioning profile). On Android, anyone with the link can install.

For anything beyond a small dev team, push the build to TestFlight or Play Internal Testing instead. Less friction, no UDID dance.

5. Daily workflow

Once installed, the loop is the same as Expo Go:

npx expo start --dev-client

The app shows a launcher with recently used Metro URLs. Tap one, you're in. Shake the device for the dev menu. Fast Refresh works. Everything you remember from Expo Go is still there.

The pitfalls nobody warns you about

Native module updates require new builds

Upgrading react-native-reanimated, react-native-screens, or anything with a native component means a new dev client build. Communicate this to your team or you'll get "why is the app crashing on my machine" messages every week.

We pin native dependency versions and bump them deliberately, with a Slack heads-up: "new dev client at this link, install before Monday."

Config plugin order matters

If you use multiple config plugins that modify the same native file, the order in app.json determines who wins. We've debugged a missing NSCameraUsageDescription for an hour before realising a later plugin was overwriting it.

iOS simulator builds and device builds aren't interchangeable

You need separate builds for simulator (x86_64/arm64-sim) and physical devices. EAS handles this if you have separate profiles. If you forget, you'll waste 20 minutes wondering why the .app won't install on your iPhone.

Don't ship the dev client to the store

Production builds should use a separate profile without developmentClient: true. Apple will reject anything with the dev launcher visible, and even if they didn't, you don't want testers shaking the device into your debug menu.

What about plain bare React Native?

There's a third option people forget: a bare React Native app with the Expo modules library installed selectively. You get full native control, you can still use expo-image, expo-router, and friends, but you lose the managed workflow conveniences (auto-generated native projects, simple app.json configuration).

We reach for bare RN when a project has a large existing native codebase to integrate — for example, an enterprise app where the client already has Swift modules they want to keep. For greenfield work, managed Expo with a dev client wins almost every time.

If you're weighing this against fully native Swift or Kotlin, our mobile development services page covers when we'd recommend each path. Short version: native still wins for graphics-heavy apps, deep OS integration, or when you only need one platform.

Where we'd start

If you're on Expo Go today and feeling the squeeze, do this on Monday morning: add expo-dev-client, run eas build:configure, and kick off a development build for both platforms before lunch. By afternoon you'll have a binary you can install, and from that point your team's velocity goes up — not down.

The switch feels intimidating because it crosses the line from "managed" into "you own the build." In practice, EAS handles 90% of what used to be the painful parts. The remaining 10% — credentials, plugin order, dependency discipline — is the price of admission for a real production app, and you were going to pay it sooner or later anyway.

#React Native#Expo#Mobile Development#EAS

Want a team like ours?

72Technologies builds production software for the kind of teams who actually read this blog.

Start a project
Expo Dev Client vs Expo Go: 2026 Migration Guide · 72Technologies