Ship Expo Updates (OTA) in Minutes: A Complete Turbopush Getting Started Guide
Step-by-step guide to setting up OTA updates in your Expo app with Turbopush, a cost-effective alternative to EAS Updates with gradual rollouts and instant rollbacks.
If you've ever needed to fix a critical bug in your Expo app without waiting for App Store review, or wanted to roll out features instantly to your users, you're in the right place. Turbopush makes Over-The-Air (OTA) updates simple, fast, and reliable.
Looking for a cost-effective alternative to EAS Updates? Turbopush offers the same power and flexibility at a fraction of the cost, with additional features like gradual rollouts, instant rollbacks, and detailed analytics.
This guide will walk you through setting up Turbopush in your Expo project from scratch. Whether you're new to Over-The-Air updates or migrating from another solution, you'll be shipping updates in no time.
What is Turbopush?
Turbopush is an Over-The-Air (OTA) update platform that lets you push JavaScript bundle updates directly to your users' devices without going through app store reviews. Think of it as a deployment pipeline for your mobile app's code - similar to how you deploy web apps, but for React Native and Expo.
Perfect for:
- Bug fixes that can't wait for app store approval
- A/B testing new features
- Gradual rollouts to specific user segments
- Quick iterations during development
Want to See It in Action First?
Before diving into the setup, you can test OTA updates right now with our pre-built Expo example app. No configuration needed - just scan and experience instant updates:
This working example lets you:
- See how OTA updates download and install
- Test mandatory vs. optional updates
- Experience rollback functionality
- Check update status in real-time
Takes less than 2 minutes to try. Once you see it working, you'll know exactly what you're building!
Important: Turbopush does NOT work with Expo Go
Due to technical limitations, Turbopush requires native code modifications that aren't possible in the Expo Go app. You'll need to create a custom development build with npx expo prebuild,
This is a one-time setup. Once you have a custom build installed on your device, OTA updates will work seamlessly.
Step 1: Install the Turbopush CLI
The Turbopush CLI is your command center for managing releases. Install it as a dev dependency in your project:
npm install --save-dev @turbopush/cliyarn add --dev @turbopush/clipnpm add --dev @turbopush/cliVerify the installation worked:
npx turbopush --versionyarn turbopush --versionpnpm turbopush --versionYou should see the CLI version printed out. If you do, you're good to go!
Step 2: Create Your Turbopush Account
Head over to https://app.turbopush.org/sign-up and create your free account. The process is straightforward - just your email and you're in.
Step 3: Authenticate the CLI
Now let's connect your local CLI to your Turbopush account:
npx turbopush loginyarn turbopush loginpnpm turbopush loginThis command will:
- Open your browser for authentication
- Generate a secure access key
- Prompt you to paste that key back in your terminal
Once you see a success message, verify you're logged in:
npx turbopush whoamiyarn turbopush whoamipnpm turbopush whoamiSet Your Default Organization
If you're working with a team or have multiple organizations, set your default:
npx turbopush org set <your-organization-slug>yarn turbopush org set <your-organization-slug>pnpm turbopush org set <your-organization-slug>Not sure what your organization slug is? List them all:
npx turbopush org listyarn turbopush org listpnpm turbopush org listStep 4: Register Your Apps
Here's an important detail: you need to create separate apps for iOS and Android. This ensures each platform gets the right update packages.
iOS
npx turbopush app add MyApp-iOS --appSlug myapp-iosyarn turbopush app add MyApp-iOS --appSlug myapp-iospnpm turbopush app add MyApp-iOS --appSlug myapp-iosAndroid
npx turbopush app add MyApp-Android --appSlug myapp-androidyarn turbopush app add MyApp-Android --appSlug myapp-androidpnpm turbopush app add MyApp-Android --appSlug myapp-androidThe --appSlug parameter is optional but recommended. It's used to identify your app in the CLI and API. If you don't provide it, Turbopush will generate one from your app name.
Save Your Deployment Keys
After creating each app, you'll see output like this:
┌────────────┬─────────────────────────────────────┐
│ Name │ Deployment Key │
├────────────┼─────────────────────────────────────┤
│ Production │ dk_19ffa8fc2a91f2cd9afb3bfecafef06d │
├────────────┼─────────────────────────────────────┤
│ Staging │ dk_5g5dc7aa6197c1f292cd12ca28f39bb3 │
└────────────┴─────────────────────────────────────┘Write these keys down! You'll need them in the next step. Each app gets two deployment keys:
- Staging: For testing updates before going live
- Production: For your production users
Step 5: Install the Turbopush SDK
Now let's add Turbopush to your Expo project:
npx expo install @turbopush/react-native-code-push @turbopush/turbopush-expo-plugin expo-build-propertiesyarn expo install @turbopush/react-native-code-push @turbopush/turbopush-expo-plugin expo-build-propertiespnpm expo install @turbopush/react-native-code-push @turbopush/turbopush-expo-plugin expo-build-propertiesThis installs three packages:
@turbopush/react-native-code-push: The core SDK@turbopush/turbopush-expo-plugin: Expo configuration pluginexpo-build-properties: To set the minimum iOS deployment target (15.5 required)
Step 6: Configure Your App
Open your app.json (or app.config.js) and add the Turbopush configuration:
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"ios": {
"deploymentTarget": "15.5"
}
}
],
[
"@turbopush/turbopush-expo-plugin",
{
"android": {
"CodePushDeploymentKey": "your-android-staging-key"
},
"ios": {
"CodePushDeploymentKey": "your-ios-staging-key"
}
}
]
]
}
}Replace your-android-staging-key and your-ios-staging-key with the actual keys from Step 4.
Note: The expo-build-properties plugin sets the iOS deployment target to 15.5, which is required by Turbopush. If you're already targeting iOS 15.5 or higher, you can skip this plugin.
Pro tip: Use environment variables for deployment keys so you can easily switch between Staging and Production:
Step 7: Run Prebuild
Before building, you need to generate the native code with prebuild:
npx expo prebuildyarn expo prebuildpnpm expo prebuildThis command generates the ios and android folders with all the necessary native configurations from your plugins.
Step 8: Integrate CodePush in Your Code
The final code step is to wrap your app with the CodePush higher-order component. This is what checks for and downloads updates.
Open your root component (usually App.tsx or App.js) and add:
import codePush from "@turbopush/react-native-code-push";
function App() {
// Your app code here
return (
// Your app components
);
}
export default codePush(App);That's it for the code! The codePush() wrapper automatically handles checking for updates when your app starts.
Want More Control?
You can customize the update behavior by passing options directly to the codePush() wrapper:
Interactive updates (show dialog and install immediately):
import codePush from "@turbopush/react-native-code-push";
function App() {
// Your app code
return (
// Your app components
);
}
export default codePush({
updateDialog: true,
installMode: codePush.InstallMode.IMMEDIATE
})(App);Custom update dialog:
export default codePush({
updateDialog: {
title: "Update Available",
optionalUpdateMessage: "A new version is available. Install now?",
optionalInstallButtonLabel: "Install",
optionalIgnoreButtonLabel: "Later"
},
installMode: codePush.InstallMode.IMMEDIATE
})(App);Step 9: Build and Run Your App
Before you can push updates, you need to build and run your app at least once. This creates the native binary that will receive updates:
iOS (simulator or device)
npx expo run:ios --configuration Releaseyarn expo run:ios --configuration Releasepnpm expo run:ios --configuration ReleaseAndroid (emulator or device)
npx expo run:android --variant releaseyarn expo run:android --variant releasepnpm expo run:android --variant releaseImportant: We're using --configuration Release (iOS) and --variant release (Android) to build in production mode. This ensures the app behaves exactly like it will in production with OTA updates enabled.
This will compile the native code and install the app on your simulator/emulator or device. This is your baseline - all future OTA updates will be applied to this binary.
Step 10: Release Your First Update
Now for the exciting part - pushing your first update! Make a small change to your app (add some text, change a color, whatever you want to test).
Then release it to Turbopush using the Expo-specific command:
iOS (replace "1.0.0" with your app version)
npx turbopush release-expo myapp-ios ios "1.0.0"yarn turbopush release-expo myapp-ios ios "1.0.0"pnpm turbopush release-expo myapp-ios ios "1.0.0"Android
npx turbopush release-expo myapp-android android "1.0.0"yarn turbopush release-expo myapp-android android "1.0.0"pnpm turbopush release-expo myapp-android android "1.0.0"The CLI will:
- Bundle your JavaScript code using Expo's bundler
- Upload it to Turbopush
- Make it available to your app immediately
Important: The version number ("1.0.0") must match exactly what's in your app.json under expo.version.
Release with Options
You can customize your release with additional parameters:
npx turbopush release-expo myapp-ios ios "1.0.0" --deploymentName "Production" --description "Critical bug fixes" --mandatory --rollout 50yarn turbopush release-expo myapp-ios ios "1.0.0" --deploymentName "Production" --description "Critical bug fixes" --mandatory --rollout 50pnpm turbopush release-expo myapp-ios ios "1.0.0" --deploymentName "Production" --description "Critical bug fixes" --mandatory --rollout 50Parameters:
--deploymentNameor-d: Target deployment (default: "Staging")--descriptionor--des: Release notes--mandatoryor-m: Force users to install this update--rolloutor-r: Gradual rollout percentage (e.g., 25 = 25% of users)
Step 11: Test Your Update
Open your app on the test device. You should see one of these scenarios:
- Immediate update (mandatory): If your app was closed, it downloads and applies the update on restart
- Background update (non-mandatory): If your app was running, it downloads the update and applies it on the next restart
Check your device logs to see the update process in action. You should see messages about checking for updates, downloading, and installing.
Common Issues and Quick Fixes
No updates available
- Double-check your deployment keys are correct
- Verify you're targeting the right deployment (Staging vs Production)
- Make sure your app version matches the release target version
Binary version mismatch
Your release target version must match exactly what's in your app.json. If your app is 1.0.0, release to 1.0.0, not 1.0.1.
Updates not installing
Make sure codePush() is wrapping your root component. The wrapper is what enables the update functionality.
What's Next?
Congratulations! You've successfully set up Turbopush and pushed your first OTA update. Here are some things to explore next:
Multi-Deployment Strategy
Use Staging for testing and Production for live users:
Test on Staging First
npx turbopush release-expo myapp-ios ios "1.0.0" -d Stagingyarn turbopush release-expo myapp-ios ios "1.0.0" -d Stagingpnpm turbopush release-expo myapp-ios ios "1.0.0" -d StagingPromote to Production
npx turbopush promote myapp-ios Staging Productionyarn turbopush promote myapp-ios Staging Productionpnpm turbopush promote myapp-ios Staging ProductionMonitor Your Releases
Check your deployment history and see how users are adopting updates:
npx turbopush deployment history myapp-ios Productionyarn turbopush deployment history myapp-ios Productionpnpm turbopush deployment history myapp-ios ProductionManage Updates via Dashboard
While the CLI is powerful, you can also manage and monitor everything through the Turbopush web dashboard at https://app.turbopush.org.
The dashboard gives you:
- Visual deployment history: See all your releases with timestamps, descriptions, and rollout percentages
- Real-time metrics: Track how many users have downloaded and installed each update
- Version distribution: See which versions your users are running
- Easy rollbacks: Rollback problematic updates with a single click
- Team collaboration: Manage team access and permissions
This is particularly useful when you need to quickly check the status of a deployment or share insights with non-technical team members who might not be comfortable with the CLI.
Advanced Update Strategies
- Mandatory updates: Force users to install critical fixes
- Gradual rollouts: Release to 10% of users, then 50%, then 100%
- Target specific versions: Send different updates to different app versions
Why Turbopush?
If you've used other OTA update solutions, here's what makes Turbopush different:
Cost-Effective Alternative to EAS Updates: Get the same power and flexibility at a fraction of the cost. Turbopush offers all the OTA capabilities you need without the premium pricing of Expo's EAS Updates.
100% CodePush Compatible: Drop-in replacement for AppCenter CodePush. No code changes needed - just update your deployment keys.
Universal Platform Support: Works with bare React Native, Expo, and the New Architecture (Fabric + TurboModules).
Rich Analytics Dashboard: Track install rates, version adoption, rollback events, and detailed user metrics in real-time.
Affordable Pricing: Pay-as-you-grow with a generous free tier. Significantly more cost-effective than EAS Updates without compromising features.
Advanced Features: Gradual rollouts, instant rollbacks, version targeting, mandatory updates, and delta updates for minimal bandwidth usage.
Modern Developer Experience: Beautiful CLI, TypeScript SDK, comprehensive docs, and excellent support.
Wrapping Up
OTA updates are a game-changer for mobile development. What used to take days (or weeks) of app store review now takes seconds. Bug fixes, feature flags, A/B tests - all deployable instantly.
Turbopush makes this power accessible with a simple CLI and minimal setup. You went from zero to shipping updates in about 10 steps, and now you have a deployment pipeline that rivals web development.
Want to learn more? Check out:
Happy shipping! 🚀
How is this guide?
Migrating from AppCenter CodePush to Turbopush: The Complete Guide for React Native
A step-by-step guide to migrating your React Native app from the discontinued AppCenter CodePush to Turbopush, a 100% compatible drop-in replacement.
What Are Over-The-Air Updates and Why They Matter for React Native
An explanation of what OTA updates are, how they work in React Native, and a pricing comparison between Turbopush and Expo Updates to help you choose the right platform.