Use CodePush-compatible OTA updates in Expo with Revopush 2.0, custom release scripts, and binary diffs based on the app binary.

You can keep the Expo SDK and still use a CodePush-style OTA release workflow. Revopush adds that OTA layer without asking you to stop using Expo.
EAS Update is Expo's hosted OTA service. If your release process already runs through EAS, use it.
If you already have release scripts, deployment gates, CI jobs, and rollback habits from a CodePush-style setup, moving the whole process into a different release model can be unnecessary work. Revopush 2.0 gives those projects a CodePush-compatible path through the Revopush SDK and Expo config plugin.
Revopush 2.0 can use the app binary as the base release, so the first OTA after a native release can already be a patch instead of a full bundle download.
EAS Update is Expo's hosted OTA service for apps using expo-updates. CodePush-style OTA is a different workflow. It is organized around apps, deployments, release commands, rollbacks, and CI/CD automation.
Revopush brings that workflow to Expo through the Revopush SDK and an Expo config plugin. It does not replace Expo SDK, Expo Router, or your existing project structure.
EAS Update uses Expo concepts such as branches, channels, and EAS-hosted release automation. If your team is already built around that model, there may be no reason to change it.
This usually comes up in projects that already have staging and production deployments, release commands in CI, promotion and rollback habits, internal approvals, or self-hosting requirements. Rebuilding that process around a new OTA model can be more work than the app needs.
For those apps, Revopush keeps OTA behavior CodePush-compatible while the project stays in Expo. The config plugin applies the native setup. The SDK checks for OTA updates at runtime.
Because this requires native configuration, it does not run inside Expo Go. Use a native build generated through prebuild, EAS Build, or your own native build pipeline.
If the update system ships a full JavaScript bundle, a one-line fix may still require users to download several megabytes. That slows down rollout, hurts users on weak networks, and increases bandwidth cost.
Revopush 2.0 uses binary diff updates.
Common OTA flow:
App Store binary
-> full OTA update
-> diff update
-> diff updateRevopush 2.0 flow:
App Store binary / base release
-> diff update
-> diff update
-> diff updateTo use Revopush 2.0 diff updates, create a base release for the specific binary version of the app. That base release is a snapshot of the JavaScript bundle and assets shipped with the IPA, APK, or AAB. Revopush uses it as the baseline for future diffs.
Users can receive small OTA patches from the first Revopush release for that binary baseline. They do not need to download a full OTA update first.
Start by installing the SDK:
npx expo install @revopush/react-native-code-pushInstall the Expo config plugin:
npx expo install @revopush/expo-code-push-pluginAdd the plugin to app.json, app.config.js, or app.config.ts, and add your Revopush deployment keys:
{
"plugins": [
[
"@revopush/expo-code-push-plugin",
{
"ios": {
"CodePushDeploymentKey": "YOUR_IOS_DEPLOYMENT_KEY",
"CodePushServerUrl": "https://api.revopush.org"
},
"android": {
"CodePushDeploymentKey": "YOUR_ANDROID_DEPLOYMENT_KEY",
"CodePushServerUrl": "https://api.revopush.org"
}
}
]
]
}Then apply the native configuration:
npx expo prebuild --cleanAfter every change to Revopush settings inside the Expo config, run prebuild again so the native iOS and Android projects receive the updated configuration.
In JavaScript, import the SDK and export your root layout or root component through codePush().
For Expo Router:
import { Stack } from "expo-router";
import codePush from "@revopush/react-native-code-push";
function RootLayout() {
return <Stack />;
}
export default codePush(RootLayout);For a non-router app, wrap your root component the same way:
import codePush from "@revopush/react-native-code-push";
function App() {
return null;
}
export default codePush(App);The wrapper lets the SDK check for an available OTA bundle and load the right JavaScript bundle for the current app binary.
The AI Skill can install the SDK, add the Expo config plugin, configure placeholders for deployment keys, run prebuild, and wrap the root layout with codePush().
Use a prompt like:
Integrate Revopush OTA into my Expo project. Install the SDK and the Expo config plugin, configure deployment key placeholders in my app config, run prebuild, and wrap my root layout with
codePush().
You still need a Revopush app, deployment keys, and the Revopush CLI to publish releases. The AI Skill handles the in-codebase integration, not the account or release operation.
Create the base release from the binary:
revopush release-native <APPLICATION_NAME> ios ./path_to_ipa/app.ipa
revopush release-native <APPLICATION_NAME> android ./path_to_apk/app.apkPublish Expo OTA updates with:
revopush release-expo <APPLICATION_NAME> android -d <DEPLOYMENT_NAME> --mandatory
revopush release-expo <APPLICATION_NAME> ios -d <DEPLOYMENT_NAME> --mandatoryAfter the base release exists, Revopush can generate diffs from the JavaScript bundle and assets already included in the app store binary.
If the Expo release process already runs through EAS Update, stay there. Use Revopush when the app needs CodePush-compatible deployments, custom CI commands, or diff updates that start from the app binary baseline.