expo-updates. One publish can target both Android and iOS; you do not run separate OTA pipelines per platform unless you choose a single platform on purpose.
Configuration lives in the Meridian-Mobile app:
app.config.js:updates.url,expo.extra.eas.projectId,runtimeVersion(see below), and theexpo-updatesplugin.eas.json: each build profile sets achannel(for exampleproduction,testflight,preview). Installed binaries only receive updates published to their channel.
Runtime version and expo.version
runtimeVersion uses the appVersion policy: the runtime is tied to the version field under expo in app.config.js at publish time, and it must match the runtime baked into the binary when that build was produced.
- For JS/asset-only fixes aimed at existing App Store / Play installs: do not bump
expo.versioninapp.config.jsunless you also ship new native builds with that version. If you bumpversionand only runeas update, devices on the old native build will not match the new runtime and will not apply the update. - When you do ship a new native release, align
version(and native versioning as needed), then future OTAs target that runtime.
Prerequisites
- EAS CLI available (for example
npx eas-cli). - Logged into the correct Expo account:
npx eas-cli login. - Working directory:
Meridian-Mobile(repository root for the mobile app).
Match the channel to the installed binary
Publish updates to the same channel as the EAS build profile used to produce the installed app. Examples fromeas.json:
| Typical use | Channel (profile) |
|---|---|
| Production store builds | production |
| TestFlight | testflight |
| Internal / preview | preview, preview-android, apk, ad-hoc, development, etc. |
Publish an update
FromMeridian-Mobile:
- Both platforms (default): omit
--platformor pass--platform all. - One platform only:
--platform androidor--platform ios(unusual; use when intentional).
--branch <name> when your Expo project maps channels to branches in the Expo dashboard. See EAS Update for branch vs channel behavior.
Verify
- CLI:
npx eas-cli update:list(and relatedeas update:*commands). - On device: use a release build (not the dev client / not
__DEV__). In the app, Settings includes app info such as channel, runtime, and update id when OTA is active.
What OTA cannot replace
These still require a new EAS build and store submission (or internal distribution):- Native code or dependency changes
- New permissions or entitlements
- Changes that require editing native projects or config plugins in a way that is not JS-only
Quick reference
| Goal | Command |
|---|---|
| Production OTA (Android + iOS) | npx eas-cli update --channel production -m "…" |
| TestFlight channel | npx eas-cli update --channel testflight -m "…" |
| List recent updates | npx eas-cli update:list |
package.json scripts such as build:ios:production and build:android:production in Meridian-Mobile).
Related pages
Mobile development builds
EAS dev-client installs and native debugging before you ship OTAs.
Mobile analytics
Client event taxonomy and how mobile telemetry aligns with the platform pipeline.
Getting started
Local setup when you work across the Meridian and Meridian-Mobile clones (sibling folders on disk).
EAS Update (Expo docs)
Official overview of EAS Update channels and runtime behavior.
Runtime versions (Expo)
How Expo matches updates to native binaries.
Publishing an update (Expo)
Step-by-step publishing flow from Expo’s guide.