Implementing Over-the-Air Updates (EAS Update)
1. Configuring EAS Update
| Property | Value | Description |
|---|---|---|
| runtimeVersion | "1.0.0" |
Unique identifier for the runtime version of your app |
| updates.enabled | true |
Enables over-the-air updates for the app |
| updates.checkAutomatically | "ON_LOAD" |
How often to check for updates: "ON_LOAD", "ON_ERROR", or "NEVER" |
| updates.fallbackToCacheTimeout | 0 |
Time in milliseconds to wait before falling back to cached version if update fails |
Example: eas.json configuration
{
"cli": {
"version": "latest"
},
"build": {
"release": {
"channel": "production"
}
},
"updates": {
"enabled": true,
"checkAutomatically": "ON_LOAD",
"fallbackToCacheTimeout": 0
}
}
Note: The
runtimeVersion must be updated whenever you want to force an update for users.
Warning: Make sure to set
updates.enabled to true in production builds to enable OTA updates.
2. Creating Updates
| Command | Description | Notes |
|---|---|---|
| eas update | Creates a new over-the-air update for your app | Must be run from the root of your project |
| eas update --branch <branch-name> | Creates an update for a specific branch | Useful for managing different environments (e.g., staging, production) |
| eas update --message "<message>" | Attaches a message to the update | Helps with version control and team communication |
Note: Updates are only available for apps built with EAS Build.
Warning: Ensure that your app's runtime version matches the update's target runtime version to avoid compatibility issues.
3. Creating Update Branch
| Property | Value | Description |
|---|---|---|
| branch.name | main |
Name of the branch to create update for |
| branch.description | Production branch for EAS Update |
Description of the branch |
| branch.isProduction | true |
Indicates if this is a production branch |
Example: Create a new update branch
expo update:branch:create --name 'staging' --description 'Staging environment branch' --isProduction false
Note: Update branches are managed through EAS Build and must be configured in your
eas.json file.
4. Setting Update Message
| Property | Description | Values |
|---|---|---|
| message | Message to display to the user when the update is available | string |
Example: Setting Update Message
{"message": "A new version of the app is available with bug fixes."}
5. Publishing to Channel
| Command | Description | Notes |
|---|---|---|
| eas update --channel <channel-name> | Publishes the latest build to a specified channel | Must be run from the project root directory |
| eas update --channel <channel-name> --message "Update message" | Publishes with a custom update message | Useful for tracking changes in the EAS Console |
Example: Publishing to a Channel
eas update --channel production --message "Fixed critical bug in login flow"
Note: Updates are only available to users who have the
expo-updates package installed and configured.Warning: Ensure that the channel name matches the one configured in your app's
app.json or app.config.js.| Channel Name | Usage | Notes |
|---|---|---|
| production | For live app releases | Typically used for production builds |
| staging | For testing before production | Useful for QA and internal testing |
| development | For local development and testing | Not recommended for production use |
6. Using Runtime Version
| Property | Value | Description |
|---|---|---|
| expo.runtimeVersion | "1.0.0" |
Defines the runtime version for over-the-air updates |
| expo.runtimeVersion.policy | "sdk-version" |
Policy for generating runtime version based on SDK version |
Example: Setting Runtime Version in app.json
{
"expo": {
"name": "MyApp",
"slug": "my-app",
"runtimeVersion": "1.0.0"
}
}
Note: Runtime version must be a string and should follow semantic versioning (e.g.,
1.0.0, 2.1.3). It is used to determine which updates are compatible with the current app build.
7. Implementing Update Hooks
Update hooks in Expo allow you to customize the behavior of over-the-air updates. These hooks are functions that are called at specific points during the update lifecycle.
| Hook | Description | Usage |
|---|---|---|
| shouldUpdate | Called before an update is applied. Allows you to conditionally prevent the update. | |
| onUpdate | Called after an update is successfully applied. | |
| onError | Called if an error occurs during the update process. | |
Example: Implementing shouldUpdate Hook
export default function shouldUpdate() {
// Prevent update if app is in foreground
return false;
}
Example: Implementing onUpdate Hook
export default function onUpdate() {
// Log update event
console.log('App updated to new version');
}
Example: Implementing onError Hook
export default function onError(error) {
// Send error to crash reporting service
console.error('Update failed:', error);
}
8. Checking for Updates
| Method | Description | Return Type | Notes |
|---|---|---|---|
| Updates.checkForUpdate() | Checks if there is an available update | Promise<UpdateInfo> |
Returns update info if available, otherwise null |
| Updates.isUpdateAvailable() | Checks if an update is available | Promise<boolean> |
Simple boolean check for update availability |
Example: Checking for Updates
import * as Updates from 'expo-updates';
const checkForUpdate = async () => {
const updateInfo = await Updates.checkForUpdate();
if (updateInfo.isAvailable) {
console.log('Update available:', updateInfo.updateUrl);
} else {
console.log('No update available');
}
};
checkForUpdate();
Example: Simple Update Check
import * as Updates from 'expo-updates';
const isUpdateAvailable = async () => {
const isAvailable = await Updates.isUpdateAvailable();
if (isAvailable) {
console.log('An update is ready to install');
} else {
console.log('No update available');
}
};
isUpdateAvailable();
Note: Updates are only checked when the app is running in a release build. In development, updates will not be fetched.
9. Fetching Updates
| Property | Description | Default |
|---|---|---|
| expo-updates | Module for managing over-the-air updates | n/a |
| updateUrl | URL to fetch update manifest from | From EAS Build config |
| shouldRollBack | Whether to rollback to previous version if update fails | false |
Example: Fetching Updates
import * as Updates from 'expo-updates';
async function fetchAndApplyUpdate() {
try {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
await Updates.reloadAsync();
}
} catch (error) {
console.error('Failed to fetch update:', error);
}
}
Note: Updates are only fetched when the app is running in a release build.
Warning: Ensure that your update URL is correctly configured in EAS Build settings.
10. Reloading App
| Method | Description | Notes |
|---|---|---|
| reload() | Triggers a full app reload from the server | Useful for applying over-the-air updates |
| reloadAsync() | Asynchronously reloads the app | Returns a promise that resolves when reload completes |
Note: The
reload() function will only work if the app is running in an environment that supports over-the-air updates, such as EAS Update.
11. Rolling Back Updates
| Option | Values | Notes |
|---|---|---|
| eas update:rollback | eas update:rollback |
Command to roll back to a previous update |
| --to | <update-id> |
Roll back to a specific update ID |
| --platform | android, ios |
Target platform for rollback |
Note: Ensure the update ID corresponds to a valid previous release in your deployment history.
Warning: Rolling back updates may cause inconsistencies if the app's codebase has changed significantly since the rollback point.
12. Viewing Update History
| Field | Description | Value |
|---|---|---|
| updateId | Unique identifier for the update | 12345678-1234-1234-1234-123456789012 |
| runtimeVersion | Runtime version of the update | 1.0.0 |
| branch | Branch name the update was published to | main |
| createdAt | Timestamp when the update was created | 2025-04-01T10:00:00Z |
| message | Release notes or message for the update | Fixed critical bug in login flow |