Expo Go is somebody else's app running your JavaScript. A development build is your app.
Expo Go is a finished app that Expo compiled, published and cannot change for you. It carries a fixed set of native libraries, and your JavaScript is a guest inside it. A development build is your own project compiled into your own app, with the expo-dev-client library added so it can load code from your machine. Expo calls that essentially your own version of Expo Go, free to use any native libraries and change any native configuration. Both loops reload JavaScript the same way. Everything else follows from who owns the native half.
This page is for someone holding a React Native and Expo project they did not type, trying to work out which of these two they are supposed to use. Every claim below comes from Expo's own documentation, read on 17 October 2026, with the date Expo stamps on each page. If you are still weighing Flutter against React Native, that is a different argument and it comes before this one.
Start hereThe short version
One line of native code decides it and you can read that line today.
Expo Go works until your project needs native code that Expo Go does not already contain. At that point it stops working, not gradually but on the first call, and no amount of restarting helps. So the choice is not a preference. It is a fact about your dependency list, and the dependency list is in your repository.
The practical reading for a handed-over project is this. Use Expo Go if you want to poke at screens and logic in the next ten minutes and the project happens to fit. Make a development build if you intend to live with this app, because every item on the list of things Expo Go cannot do is something a shipping app eventually needs. Expo itself puts it bluntly: Expo Go is a learning environment and sandbox, and a production project should have a development build so the native app and its dependencies are controlled by the project.
What does Expo say the difference actually is?
Expo splits any React Native app into two halves and the whole subject makes sense once you hold them apart. The native app is the thing installed on the device. It contains the compiled native code of every library the project depends on, plus the icon, the name and the splash screen. The JavaScript bundle is your screens and your logic. In a shipped app there is one bundle, called main.js, packaged inside. In development that bundle is served live off your machine and reloads as you type.
Expo Go is a pre-built native app. Expo's own words: it works like a playground and it cannot be changed after you install it. The native half was decided by Expo, built by Expo and uploaded to the stores by Expo. You are supplying the other half. The sentence that explains every limitation on this page is Expo's own: only APIs and libraries that were bundled in the native app can be used.
A development build is the same arrangement with the native half handed back to you. It is your project compiled, with the expo-dev-client library installed, which Expo says augments the built-in React Native development tooling. You get network request inspection and a launcher screen that lets you point the app at different development servers, which is how two people on a team share one build. The dev menu opens with Cmd and D, or Ctrl and D, or by shaking the phone.
Expo documents three ways to produce that build and is explicit that all three produce the same thing. Locally with Expo CLI, using Android Studio or Xcode on your own machine, which needs no Expo account. On EAS servers in the cloud, which needs no native toolchain and can make iOS builds from Windows or Linux. Or the same EAS build run on your own machine with a local flag, where EAS still handles credentials and signing. The difference between them is where the compiler runs and what you had to install first, not what comes out.
Expo, development builds FAQ, page dated 3 September 2026, read 17 October 2026
Check yours
Which loop does the thing you are testing need
Tick what you are about to work on. The reason under each answer is Expo's, not ours.
Nothing ticked. If every item on your list is JavaScript, Expo Go will carry you, and the first native library you add ends that.
What can Expo Go not run?
Expo publishes the list, under a heading that says what cannot be done in Expo Go and why, and the why is always the same. The native app is immutable once installed. Five entries follow from that.
Native libraries that are not already inside Expo Go. Expo works the example through carefully, and it is worth following because the failure is confusing the first time. Install a package with native code and both halves land in node_modules. Your JavaScript bundle uses only the JavaScript half. That bundle reaches Expo Go and calls into native code that is not there. Expo's example of a library that works is react-native-webview, which is bundled in Expo Go. Its example of one that does not is react-native-firebase, where the new bundle hot reloads and then errors immediately. Expo states there is no way to get the native code into Expo Go unless it was in the bundle Expo uploaded to the stores.
Your app icon, your app name and your splash screen. You can ship all three from a project you only ever opened in Expo Go, and they will be correct in the store build. You just cannot look at them while you work. Expo Go draws a splash screen that is your icon on a solid colour, which it calls a dev-only emulation to give you a rough idea, and it cannot run SplashScreen.setOptions to animate anything. These assets ship with the native bundle.
Remote push notifications, meaning the ones sent from a server to the phone. Notifications the app raises itself do work in Expo Go. Expo's reasoning for the split is that a push service has to be tied to your own notification certificates, and making it work in Expo Go tends to confuse people later about why production behaves differently. Then App Links on Android and Universal Links on iOS, both of which need a two-way association in which the native app carries the linked website's URL. The native app is not yours to edit, so the association cannot be made.
And the fifth, which is the one that stops people before they even reach the other four. Each build of Expo Go supports exactly one Expo SDK version, and the project's version has to match. The expo dependency in package.json is what sets the project's version, so that one line tells you which Expo Go you need. On Android, on the Android Emulator and on the iOS Simulator you pick a matching build from expo.dev/go and install it. On a physical iPhone the answer is less comfortable, and it is the next section.
Can you still install Expo Go on an iPhone?
This is where the usual advice has gone stale, so it is worth being exact. Expo's troubleshooting page for the SDK mismatch error, dated 3 September 2026, says Expo Go on the Apple App Store stops at SDK 54, and that SDK 55 and later are not available there. The expo-dev-client reference page currently points at the sdk-58 source tree, so a project created today sits four releases past that ceiling. The free download route that every older tutorial assumes is not available for a current project on a real iPhone.
What Expo tells you to do instead, for SDK 54 and above on a physical iPhone or iPad, is build Expo Go yourself. The command is eas go, and the output is distributed through your own TestFlight internal team, which Expo says needs an Apple Developer Program membership. The setup page spells out the rest: install TestFlight, open App Store Connect, add your own Apple ID as an internal tester, accept the email invitation. There is a further step people miss. On a physical iOS device, Expo Go opens a project from a development server only when Expo CLI and Expo Go are signed in to the same Expo account.
Read that path back and notice what it costs. To use the free playground on your own iPhone you now need a paid Apple membership, a TestFlight distribution and a build you compiled. That is the whole price of a development build, spent on getting someone else's app onto your phone instead of your own. Apple's enrollment page, read 17 October 2026, puts the Apple Developer Program annual fee at 99 USD, in local currency where available, and it belongs in your view of what an app costs to maintain whichever loop you choose, because publishing to the App Store needs it anyway.
Older projects are worse off, not better. For SDK 53 or earlier Expo says you cannot install an older version of Expo Go on a physical iOS device at all. Your options are to upgrade the project, use an Android device, use the iOS Simulator, or create a development build. Three of those four are real work, and one of them is the thing you were trying to avoid.
The other platforms are still easy, and that asymmetry is useful to know before you plan a day. Expo Go for Android comes from the Google Play Store, although Expo notes the Play version can also lag behind a new SDK release. On the Android Emulator and the iOS Simulator, Expo CLI installs Expo Go for you when you press A or I at the development server prompt. And for a development build, Expo says compiling locally with Expo CLI is the only way to install one on an iPhone without a paid Apple Developer account, while every EAS build that runs on an iPhone device needs a paid account for signing.
How much slower is a development build to live with?
Much less than the fear suggests, because the slow part happens once. The usual objection is that a development build means waiting for a compiler every time, and Expo is direct that this is not how it works. The native directories are reused on later runs. When you change only TypeScript or JavaScript, there is nothing to rebuild and you start the server with npx expo start, exactly as you would for Expo Go.
Expo names three events that do force a recompile. Installing or updating a library that contains native code. Changing your app config, meaning app.json. Upgrading your Expo SDK version. When one of those happens you run npx expo prebuild --clean to regenerate the native android and ios directories, then build again. Expo also notes you never need to run prebuild by hand the first time, because both expo run and eas build do it for you when no native directories exist.
Put a week of real work against that list and the picture changes. Screens, copy, state, navigation, data fetching and bug fixing are all JavaScript and cost nothing. Adding a library with native code is a recompile, and so is a one-line change to app.json, which is the one that surprises people, so batch your config edits. Expo is candid that building from scratch takes long enough that you will be tempted to switch tasks and lose focus. That is an argument for doing it once on a Monday, not for avoiding it.
Two details worth planning around. An iOS Simulator build installs only on simulators and an iOS device build only on devices, so if you want both you need two builds and, per Expo, a separate EAS profile for the simulator one. And neither loop tells you anything trustworthy about speed, because both serve a development bundle over your network rather than the single main.js bundle that ships. If somebody asks you about app startup time, do not answer from either one.
The same project, in the three apps it can run inside
The third column is the one people forget. A development build is not a compromise between Expo Go and the real thing. It is the real thing with developer tooling bolted on, which is why the second and third columns agree almost everywhere.
| The question | Expo Go | A development build | The build you ship |
|---|---|---|---|
| Who compiled the native app | Expo did, before you arrived | You did, or EAS did for you | You did, or EAS did for you |
| Native libraries you can call | A fixed set, chosen when Expo Go was built | Whatever your project depends on | Whatever your project depends on |
| Shows your icon, name and splash screen | No | Yes | Yes |
| Remote push notifications work | No | Yes | Yes |
| Universal Links and App Links work | No | Yes | Yes |
| JavaScript reloads from your machine | Yes | Yes | No |
| Expo SDK version it accepts | One per Expo Go build, and it has to match yours | Whatever your project is on | Whatever your project is on |
| Needs recompiling when you add a native library | Not possible either way | Yes | Yes |
Where this lands if a builder generated your project
Newly is an AI app builder. You describe an app in plain English and it writes a real React Native and Expo project you own, with two-way GitHub sync so the code is on your machine and not in somebody else's dashboard. It uploads iOS builds to TestFlight, publishes to Google Play internal testing and builds a standalone Android APK. It is $25 a month, with no free tier. It does not press submit on the App Store for you, because Apple requires the owner of the content to submit the app.
Read that against this page and the useful observation is that the builder already does the hard half of a development build. Compiling your project into your own native app, signed, installable and sent to a tester, is the step people put off for weeks. If the output you are holding went to TestFlight or to internal testing, a native build of your project has already been produced. The thing a development build adds on top is the live reload loop and the developer tooling, which matters the day you want to change a screen yourself rather than ask for it.
So whether Expo Go is open to you is a question about your repository, and you can settle it in ten minutes without asking anyone. Open package.json. The expo dependency gives the SDK version, which tells you which Expo Go you would need and, on a physical iPhone, whether the App Store route exists at all. Then read the rest of the dependency list for native packages. Expo's own npx expo-doctor@latest will flag version mismatches while you are looking, and npx expo install --fix will align packages with the installed SDK. One unbundled native library is a complete answer.
The honest limit on all of this: neither loop changes anything about what you are responsible for. The project is yours to compile, to sign and to submit, and the licence questions around who owns AI generated code do not move either. Expo Go is a way to look at your JavaScript quickly. A development build is a way to work on your app. Only one of them scales past the first native dependency, and every app that lasts acquires one.
Questions people ask about Expo Go and development builds
Expo Go is a pre-built app that Expo compiled and published, carrying a fixed set of native libraries. Your JavaScript runs inside it. Expo's own documentation calls it a playground app for students and learners. A development build is your own app, compiled from your project with the expo-dev-client library added, which Expo describes as essentially your own version of Expo Go where you are free to use any native libraries and change any native configuration. The JavaScript loop is the same in both. The difference is who owns the native half, and therefore which native code is reachable at all.
Describe the app, then keep the project that comes out
A real React Native and Expo project, synced to your own GitHub, already compiled and already sent to a tester. Whichever loop you develop in after that is your call, and you will have the dependency list in front of you to make it with.
Start building