Configuration
Configuring app.json
Section titled “Configuring app.json”To point your Expo app to your custom OTA server, update the updates section of your app.json:
{ "expo": { "updates": { "url": "https://your-worker-subdomain.workers.dev/update" }, "runtimeVersion": { "policy": "appVersion" }, "extra": { "eas": { "projectId": "your-eas-project-id" } } }}Adding the expo-channel-name header
Section titled “Adding the expo-channel-name header”You must specify which channel the device should listen to (e.g., production, staging, or main). You can pass this via the requestHeaders in your app’s code or configuration.
Runtime Versions
Section titled “Runtime Versions”Expo OTA updates are tied to a runtimeVersion. If the runtimeVersion of the update does not match the runtimeVersion of the native build, the update will be ignored.
appVersionpolicy: The easiest way to manage compatibility. Updates will only be delivered if the app’s native version (e.g., 1.0.0) matches exactly.- Fingerprint: Use
expo-updates’s fingerprinting for more granular control based on native dependencies.
Testing Updates In-App
Section titled “Testing Updates In-App”Default “Two-Boot” Behavior
Section titled “Default “Two-Boot” Behavior”By default, Expo checks for updates on launch. If an update is found, it’s downloaded in the background and applied on the next launch.
Implementing a Manual “Check for Updates” Button
Section titled “Implementing a Manual “Check for Updates” Button”You can use the expo-updates JS API to force a check and reload:
import * as Updates from 'expo-updates';
async function onCheckForUpdate() { const update = await Updates.checkForUpdateAsync(); if (update.isAvailable) { await Updates.fetchUpdateAsync(); await Updates.reloadAsync(); }}