In this guide 6 sections
Use three EAS build profiles. Send native changes through the stores and JavaScript fixes as over the air updates. Tie every update to a runtime version so it reaches only compatible binaries. Keep a rollback step ready before each release.
Set up three build profiles and keep them apart
In eas.json define development, preview and production profiles. Development builds carry the dev client and connect to a local bundler. Preview builds are internal, installable by testers through a link. Production builds are what the store receives.
Give each profile its own environment values and its own update channel. Preview should point to a staging API and a test database. Production should never share a backend with preview, or a tester’s order lands in live records.
Name builds by purpose in your tracker, not by number alone. Your support team should be able to read which build a user holds.
- development: dev client, local bundler
- preview: internal link, staging API
- production: store binary, live API
- One update channel per profile
Decide whether a change needs the store or an update
Anything that touches native code needs a new binary and a store release. That includes a new library with native modules, a changed permission, a new app icon, splash screen and an upgrade of the Expo SDK.
Screens, business logic, copy fixes and API field changes written in JavaScript can ship as an over the air update with EAS Update. Staff receive it the next time the app launches, without waiting for review.
Write this rule at the top of your release note template. A developer who must tick one of two boxes will not push a native change as an update by accident.
Use runtime versions to protect old binaries
Every binary carries a runtime version. An update only reaches binaries whose runtime version matches its own. This is the safeguard that stops a new JavaScript bundle from landing on an older app that lacks the native module it calls.
Choose a policy and keep to it. Tying the runtime version to the app version is simple. Fingerprint based versions change when native code changes and catch changes you forgot about. Whichever you choose, bump it whenever native code moves.
Field staff on old phones update late. Keep the previous runtime version’s updates available until installs on it drop away.
- Native change: new runtime version
- JavaScript change: same runtime version
- Check the fingerprint before every build
- Keep old channels alive until installs fade
Submit to the stores with a fixed checklist
Build the production profile and install it from the build link on a clean test phone. Run the smoke list: login, one full job, camera, offline entry, push notification. Only then submit.
EAS Submit can send the build to App Store Connect and Google Play. Keep store credentials in EAS secrets, not in the repository. Prepare screenshots, the privacy answers and the release notes before submission day, since review time varies.
For company apps distributed only to staff, use TestFlight, internal testing tracks or managed distribution. Keep a list of which phones run which build.
Prepare the rollback before you need it
A bad update can be undone. EAS Update lets you republish an earlier update to the same channel, or fall back to the embedded bundle. Devices return to a known state at their next launch. Practise it on preview first.
A bad binary is harder, because users hold it. Halt the staged rollout in the store console, ship a corrected build and keep an update ready that works around the fault in the meantime.
Next step: run a rehearsal this week. Publish a harmless update to preview, roll it back, time it, and write the steps into the release note.
Expo release routine sheet
A single checklist in three blocks. Before: pick the profile, confirm native or JavaScript change, set the runtime version, run the smoke list on a clean phone. During: build, submit or publish the update, watch crash reports. After: record the build number, name the rollback command and its owner, and note the date old runtime versions can be retired.
Open a blank worksheet to printQuestions owners ask
Can we ship every fix as an over the air update?
No. Only JavaScript and asset changes qualify. Anything touching native code, permissions or the SDK version needs a new binary and a store release.
What happens if an update reaches an incompatible app?
With runtime versions set correctly it should not. The update is matched only to binaries with the same runtime version, so older apps keep running their own bundle.
How often should we release?
Set a rhythm your testers can keep, such as a weekly preview build and a store release only when native work exists. Small frequent updates are easier to roll back.
Do internal staff apps need store review?
Usually yes unless distributed through managed channels such as TestFlight or internal tracks. Check each store’s current rules for private distribution.
