Skip to main content

Over-the-Air Updates

Over-the-Air (OTA) updates allow you to publish JavaScript, styling, and asset changes directly to users’ devices without rebuilding your app or going through app store review. This enables rapid bug fixes and feature deployments.

How EAS Update Works

EAS Update publishes JavaScript bundles and assets to a CDN. When users open your app:
  1. App checks for new updates on launch
  2. If available, downloads update in background
  3. Update applies on next app restart
  4. Users always get latest compatible version
What can be updated:
  • JavaScript code changes
  • React components and logic
  • Styles and layouts
  • Assets (images, fonts, etc.)
  • Configuration (app.json changes)
What requires a new build:
  • Native code changes
  • New native modules
  • Expo SDK version upgrades
  • App permissions changes
  • Native configuration (AndroidManifest.xml, Info.plist)

Setting Up EAS Update

1

Install expo-updates

Add the package to your project:
For bare React Native projects, run prebuild:
2

Configure Your Project

Run the configuration command:
This adds update configuration to your app.json:
app.json
And updates eas.json with channel configuration:
eas.json
3

Build with Update Support

Create a build that includes expo-updates:
This build will check for updates from the configured channel.
4

Publish Your First Update

Make changes to your JavaScript code, then publish:
Users on the production channel will receive this update on next app launch.

Update Channels and Branches

Channels

Channels link builds to update branches. Each build points to one channel. Common channel setup:
eas.json
How channels work:
  • Production builds → production channel → receive production updates
  • Staging builds → staging channel → receive staging updates
  • Each channel can have different update content

Branches

Branches are streams of updates published to channels. Publishing to branches:
By default, branch name matches channel name. For most use cases, you can treat channels and branches as the same concept.

Runtime Versions

Runtime version determines update compatibility. Only updates with matching runtime version will be delivered. Runtime version policies:
app.json
Policy options:
  1. appVersion (Recommended):
    • Uses version from app.json
    • Example: 1.0.0 → runtime version 1.0.0
    • Update only delivered to apps with same version
    • Clear, predictable versioning
  2. nativeVersion:
    • Uses native build numbers
    • iOS: CFBundleShortVersionString + CFBundleVersion
    • Android: versionName + versionCode
  3. sdkVersion:
    • Uses Expo SDK version
    • Example: 51.0.0
    • Deprecated, not recommended
  4. Custom string:
Runtime version workflow:
  1. Build app with runtimeVersion: 1.0.0
  2. Publish updates for runtime version 1.0.0
  3. Only users with 1.0.0 builds receive updates
  4. When native code changes, increment to 1.1.0
  5. Build new app version with 1.1.0
  6. Publish separate updates for 1.1.0

Publishing Updates

Basic Update Publishing

Platform-Specific Updates

Automatic Updates from Git

Trigger updates on Git events using EAS Workflows:
.eas/workflows/update-production.yml
Trigger with:

Update Deployment Workflow

Recommended workflow for safe deployments:
1

Develop and Test Locally

Make changes and test with Expo CLI:
2

Publish to Preview Channel

Test with internal team:
Share preview build with team for testing.
3

Publish to Staging Channel

Deploy to staging environment:
Conduct thorough QA testing.
4

Publish to Production

After staging approval:
Users receive update on next app launch.

Advanced Update Features

Gradual Rollouts

Deploy updates to a percentage of users:
Rollout strategy:
  1. Start with 10% rollout
  2. Monitor crash reports and feedback
  3. Increase to 25%, 50%, 75%
  4. Complete with 100% rollout

Republishing Updates

Promote tested update from staging to production:
This ensures exact same code tested in staging goes to production.

Rolling Back Updates

Revert to previous working update:
This prompts you to:
  1. Select channel to rollback
  2. Choose previous update to restore
  3. Confirm rollback
Users receive the previous update on next app restart. Rollback workflow:

Update Groups

Manage related updates across channels:
With eas.json:
eas.json

Monitoring Updates

EAS Update Dashboard

View update analytics at https://expo.dev/accounts/[account]/projects/[project]/updates:
  • Total downloads: How many devices fetched update
  • Successful updates: Updates applied successfully
  • Failed updates: Update errors or rollbacks
  • Platform breakdown: iOS vs Android adoption
  • Version distribution: Which runtime versions are active

Update Logs

View update details:

Runtime Metrics

Track update adoption in your app:

Update Best Practices

Testing Before Release

  1. Test locally: Use Expo Go or development builds
  2. Preview channel: Share with internal team
  3. Staging channel: QA testing with staging builds
  4. Production rollout: Gradual deployment to users

Version Management

Align updates with builds:
app.json
Increment version when:
  • Native code changes
  • New native modules added
  • Breaking changes in native configuration
  • Expo SDK upgrade
Publish updates when:
  • Bug fixes in JavaScript
  • UI/UX improvements
  • Feature toggles
  • Analytics updates
  • Non-native configuration changes

Update Messaging

Include meaningful messages:
Message should include:
  • What changed
  • Why it changed (bug fix, feature, etc.)
  • Ticket/issue reference
  • Version or sprint number

Emergency Hotfixes

For critical production bugs:

Update Size Optimization

Minimize update download size:
  1. Optimize assets:
    • Compress images
    • Use appropriate formats (WebP for images)
    • Lazy load large assets
  2. Code splitting:
    • Use dynamic imports
    • Defer non-critical code
  3. Remove unused code:
    • Tree shaking enabled by default
    • Remove console.logs in production
    • Minimize dependencies

Troubleshooting

Update Not Received

Issue: Users not getting published update Check:
  1. Runtime version mismatch:
  2. Channel configuration:
    eas.json
  3. Update not published:
  4. App not checking for updates:
    • Ensure expo-updates is installed
    • Check app.json configuration
    • Verify build includes updates URL

Update Failed to Apply

Issue: Update downloaded but not applied Solutions:
  1. Check error logs:
  2. Asset loading failure:
    • Check asset URLs are accessible
    • Verify CDN is reachable
    • Check for CORS issues (web)
  3. Corrupted update:

Wrong Runtime Version

Issue: Updates not compatible with builds Solution: Align runtime versions:
app.json
Build new version and publish matching updates:

Update Rollback Not Working

Issue: Rollback command fails or doesn’t revert Solutions:
  1. Manual rollback:
  2. Create new update:
    • Revert code changes in Git
    • Publish as new update (faster than rollback)

Next Steps