React Native OTA updates without the wait
Ship JS-layer fixes and UI changes to your React Native app in seconds, not days. Ubriot publishes OTA updates to named channels and lets you roll back instantly. Before you publish, it warns you if an update would target an older runtime than your users are on.
What Ubriot OTA updates give your React Native team
- Publish updates without App Store review
- Named channels (production, staging, etc.)
- Runtime version compatibility checks
- Instant rollback from the dashboard
- CLI command: ubriot update
- Update history and bundle storage
- Per-channel update targeting
- Works with Expo (expo-updates) and bare React Native (ubriot-updates-rn)
How React Native OTA updates work with Ubriot
Set up once, then ship updates with one command.
Step 1
Set a runtime version
The runtime version tells Ubriot which native binary a JS bundle is compatible with. Updates only land on matching binaries.
Step 2
Set up the update URL
Point your update client, expo-updates for Expo apps or ubriot-updates-rn for bare React Native, at your Ubriot update endpoint. The app checks for a new bundle on launch.
Step 3
Run ubriot update
Bundle your JS layer and publish it to a channel, production, staging, or any name you choose. Takes seconds.
Step 4
The app receives the update
On next launch, the app downloads and applies the new bundle. No App Store review, no waiting.
Step 5
Roll back instantly if needed
If a bad update ships, roll back to any previous bundle from the dashboard. Users get the previous version on next launch.
Expo or bare React Native, your choice
Same channels, same rollback, same ubriot update command. Pick the client that matches your app.
Expo
Add expo-updates, set updates.url to your Ubriot endpoint, and publish with ubriot update.
Bare React Native
Install ubriot-updates-rn, no Expo required. Same backend, same CLI.
npm install ubriot-updates-rnCommon pitfalls
These mistakes cause silent OTA failures, good to know before you ship.
reloadAsync() must be compiled into the binary, it cannot arrive via OTA
With checkAutomatically: NEVER, your binary must call checkForUpdateAsync() → fetchUpdateAsync() → reloadAsync(). Miss it and updates download but never apply, and an OTA can't add it back. Verify the sequence is compiled in before shipping.
Run ubriot update from inside your app directory, not the monorepo root
In a yarn workspaces monorepo, yarn hoists packages to the root. When you run ubriot update from the root, npx expo export resolves modules from the wrong node_modules and fails with module-not-found errors. Always cd into your app folder (e.g. products/my-app/mobile) before running ubriot update.
runtimeVersion links OTAs to binaries, never change it casually
An OTA is only delivered to devices whose installed binary declares the same runtimeVersion. Changing the value in app.json means old binaries stop receiving new OTAs instantly, and new OTAs can never reach anyone still on the old binary. Only change runtimeVersion when a native module change makes old JS bundles genuinely incompatible with the new binary.
Apple closes a version train once a build is approved
If you submit a binary and Apple approves it, that version string (CFBundleShortVersionString) is closed. Submitting another binary under the same version returns a 409 Invalid Pre-Release Train error. Bump your version field in app.json before every binary build that goes to TestFlight or the App Store.
Ship React Native OTA updates today
Fix bugs and ship UI changes in seconds with ubriot update.