Turbopush

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:

Try the Live Demo →

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/cli

Verify the installation worked:

npx turbopush --version

You 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 login

This command will:

  1. Open your browser for authentication
  2. Generate a secure access key
  3. Prompt you to paste that key back in your terminal

Once you see a success message, verify you're logged in:

npx turbopush whoami

Set Your Default Organization

If you're working with a team or have multiple organizations, set your default:

npx turbopush org set <your-organization-slug>

Not sure what your organization slug is? List them all:

npx turbopush org list

Step 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-ios

Android

npx turbopush app add MyApp-Android --appSlug myapp-android

The --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-properties

This installs three packages:

  • @turbopush/react-native-code-push: The core SDK
  • @turbopush/turbopush-expo-plugin: Expo configuration plugin
  • expo-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 prebuild

This 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 Release

Android (emulator or device)

npx expo run:android --variant release

Important: 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"

Android

npx turbopush release-expo myapp-android android "1.0.0"

The CLI will:

  1. Bundle your JavaScript code using Expo's bundler
  2. Upload it to Turbopush
  3. 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 50

Parameters:

  • --deploymentName or -d: Target deployment (default: "Staging")
  • --description or --des: Release notes
  • --mandatory or -m: Force users to install this update
  • --rollout or -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:

  1. Immediate update (mandatory): If your app was closed, it downloads and applies the update on restart
  2. 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 Staging

Promote to Production

npx turbopush promote myapp-ios Staging Production

Monitor Your Releases

Check your deployment history and see how users are adopting updates:

npx turbopush deployment history myapp-ios Production

Manage 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?