Welcome back

Opening shared build

Preparing your Mach workspace…

Preparing your secure download…

Mach
Dashboard
All guides
Release guide
July 31, 2026 · 7 min read

How to Publish OTA Updates for React Native with Mach

Set up Mach-hosted over-the-air updates, keep runtime compatibility predictable, and release safely to the right channel.
What you will finish with
A linked Mach project, a framework-specific mach.config.json, and an exact command sequence for your first release workflow.

Understand what OTA can change

An OTA release updates JavaScript bundles and assets. It cannot add a native dependency, modify iOS entitlements, change Android manifest entries, or replace the native runtime already installed on a device. Those changes always need a new binary build.
Mach uses the open-source expo-updates runtime for both Expo and bare React Native projects. Mach hosts the update artifacts and release metadata itself, so publishing does not use EAS Update and the app never receives storage credentials.
Use OTA for JavaScript, styling, images, and other compatible asset changes.
Create a new native build after changing native code, SDKs, app permissions, the runtime policy, or OTA setup.

1. Set up OTA from the project root

Run setup once in the linked project, then verify the final configuration. Mach reads the project ID, framework, channel, runtime policy, and existing update URL from mach.config.json. Interactive setup asks before installing anything it needs.
bash
mach ota setup mach ota verify
Expo and bare React Native both work
For Expo, Mach applies the packaged Expo plugin during prebuild. For React Native CLI projects, it may install Expo Modules and expo-updates, then synchronizes native configuration without running Expo prebuild.

2. Choose a channel and runtime policy

A channel controls who receives a release, while the runtime version prevents an update from reaching an incompatible binary. The default appVersion policy uses the app or package version as that compatibility boundary, which is the right starting point for most teams.
mach.config.json
{ "ota": { "channel": "production", "runtimeVersionPolicy": "appVersion" } }
Keep the precedence clear
A command-line value such as --channel or --runtime-version always overrides mach.config.json for that run. Mach otherwise keeps the project config as the source of truth.

3. Build a new OTA-enabled binary

Only native binaries built after OTA setup can check the Mach endpoint. Build and install one version for each platform you intend to update before publishing the first OTA release.
bash
mach build --platform ios --profile production mach build --platform android --profile production

4. Publish a compatible release

Publish the JavaScript and assets to the channel that matches the installed binaries. Mach exports the update, uploads the protocol manifest and assets, and activates the release for the matching project, channel, platform, and runtime.
bash
mach ota publish --channel production --platform all --message "Fix checkout flow"

5. Confirm delivery and know the launch behavior

With the default on-load behavior, a compatible update is checked and downloaded on one cold launch, then runs on the next cold launch. The OTA dashboard records unique downloaded, applied, and failed devices automatically from the Expo Updates request headers.
Use the release detail page to confirm the channel, runtime, platform breakdown, and delivery counts before broadening a rollout.
Keep going
List releases
mach ota list
Review the currently published OTA releases for the linked project.
Roll back a release
mach ota rollback --update-id <updateId>
Disable a selected active release so compatible clients receive the previous active one.
Build and release with less ceremony.
Guides for Flutter, React Native, and Expo teams that want a clear path from project setup to shipment.
All guides
Start free