<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Turbopush</title>
    <description>The latest articles on DEV Community by Turbopush (@turbopushdev).</description>
    <link>https://dev.to/turbopushdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3692731%2Fca4159d9-6ab9-4f5c-849a-e048b2e7c161.png</url>
      <title>DEV Community: Turbopush</title>
      <link>https://dev.to/turbopushdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/turbopushdev"/>
    <language>en</language>
    <item>
      <title>What Are Over-The-Air Updates and Why They Matter for React Native</title>
      <dc:creator>Turbopush</dc:creator>
      <pubDate>Sun, 04 Jan 2026 19:19:27 +0000</pubDate>
      <link>https://dev.to/turbopushdev/what-are-over-the-air-updates-and-why-they-matter-for-react-native-3n44</link>
      <guid>https://dev.to/turbopushdev/what-are-over-the-air-updates-and-why-they-matter-for-react-native-3n44</guid>
      <description>&lt;p&gt;Imagine shipping a critical bug fix to your mobile app and having it reach users within minutes—not days or weeks waiting for App Store review. That's the power of Over-The-Air (OTA) updates, and it's changing how mobile developers ship software.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore what OTA updates are, how they work in React Native, and why they're becoming essential for modern mobile development. We'll also compare pricing between major OTA platforms to help you make an informed decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly Are OTA Updates?
&lt;/h2&gt;

&lt;p&gt;Over-The-Air updates allow you to push new code directly to users' devices without going through the traditional app store submission process. Instead of uploading a new binary to Apple or Google, waiting for review, and hoping users update their apps, you can deploy changes instantly.&lt;/p&gt;

&lt;p&gt;Think of it like deploying a web application. When you push changes to your website, users see them immediately on their next visit. OTA updates bring this same workflow to mobile apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you can update OTA:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript code and logic&lt;/li&gt;
&lt;li&gt;React components and screens&lt;/li&gt;
&lt;li&gt;Styles and layouts&lt;/li&gt;
&lt;li&gt;Images and assets bundled with your code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you cannot update OTA:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native code (Swift, Kotlin, Objective-C, Java)&lt;/li&gt;
&lt;li&gt;Native dependencies and libraries&lt;/li&gt;
&lt;li&gt;App permissions and capabilities&lt;/li&gt;
&lt;li&gt;App Store metadata (name, icon, screenshots)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How OTA Updates Work in React Native
&lt;/h2&gt;

&lt;p&gt;React Native apps consist of two parts: the &lt;strong&gt;native shell&lt;/strong&gt; (compiled code that runs on the device) and the &lt;strong&gt;JavaScript bundle&lt;/strong&gt; (your React components, business logic, and UI code).&lt;/p&gt;

&lt;p&gt;When you build a React Native app, your JavaScript code gets bundled into a single file that the native shell loads at runtime. Here's where OTA updates come in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initial Install&lt;/strong&gt;: User downloads your app from the App Store. The app contains a native shell and a JavaScript bundle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update Check&lt;/strong&gt;: When the app launches, it checks a remote server for new JavaScript bundles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download&lt;/strong&gt;: If a new bundle is available and compatible with the native shell, it downloads in the background.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Apply&lt;/strong&gt;: The new bundle replaces the old one, either immediately or on the next app restart.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rollback Safety&lt;/strong&gt;: If the new bundle crashes, most OTA systems automatically rollback to the previous working version.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                     User's Device                           │
│  ┌─────────────────┐     ┌─────────────────────────────┐    │
│  │   Native Shell  │ ←── │  JavaScript Bundle (OTA)    │    │
│  │   (App Store)   │     │  - React Components         │    │
│  │                 │     │  - Business Logic           │    │
│  └─────────────────┘     │  - Styles &amp;amp; Assets          │    │
│                          └─────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘
                                    ↑
                                    │ Download new bundle
                                    │
                          ┌─────────────────┐
                          │   OTA Server    │
                          │   (Turbopush)   │
                          └─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture is what makes React Native uniquely suited for OTA updates. Unlike fully native apps where every change requires recompilation, React Native's JavaScript-based approach allows for dynamic code updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why OTA Updates Matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Speed to Market
&lt;/h3&gt;

&lt;p&gt;App Store review can take anywhere from 24 hours to several days. For critical bug fixes, that delay can mean lost users, revenue, or even legal issues. OTA updates bypass this entirely—deploy a fix in seconds, not days.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Reduced User Friction
&lt;/h3&gt;

&lt;p&gt;Users don't always update their apps. Some have automatic updates disabled, others ignore update notifications, and many simply forget. With OTA updates, users get the latest version automatically, ensuring everyone runs your best code.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. A/B Testing and Feature Flags
&lt;/h3&gt;

&lt;p&gt;Want to test a new feature with 10% of users before rolling it out to everyone? OTA platforms often include rollout controls that let you gradually deploy changes and rollback instantly if something goes wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Cost Efficiency
&lt;/h3&gt;

&lt;p&gt;Every app store submission has costs: developer time for testing, QA cycles, and the opportunity cost of waiting. OTA updates streamline this process, letting your team focus on building features instead of managing releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Emergency Response
&lt;/h3&gt;

&lt;p&gt;When a critical bug hits production, every minute counts. OTA updates let you deploy a hotfix immediately, without waiting for app store approval or hoping users update manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Turbopush?
&lt;/h2&gt;

&lt;p&gt;Turbopush is a modern Over-The-Air update platform built specifically for React Native applications. Whether you're using &lt;strong&gt;bare React Native&lt;/strong&gt; or &lt;strong&gt;Expo&lt;/strong&gt;, Turbopush integrates seamlessly with your existing workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Universal React Native support&lt;/strong&gt; — Works with bare React Native, Expo, and the New Architecture (Fabric + TurboModules)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradual rollouts&lt;/strong&gt; — Release to 10%, 50%, or any percentage of users before going full&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant rollbacks&lt;/strong&gt; — Revert problematic updates with a single command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich analytics&lt;/strong&gt; — Track install rates, version adoption, and user metrics in real-time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pricing Comparison: Turbopush vs Expo Updates
&lt;/h2&gt;

&lt;p&gt;When choosing an OTA platform, pricing is a crucial factor. Let's compare Turbopush and Expo Updates (EAS Update) across different app sizes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Pricing Models
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Expo Updates&lt;/strong&gt; charges based on &lt;strong&gt;Monthly Active Users (MAUs)&lt;/strong&gt;—the number of unique users who download at least one update during a billing period. Multiple downloads by the same user count as a single MAU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbopush&lt;/strong&gt; charges based on &lt;strong&gt;updates delivered&lt;/strong&gt;—each time a user downloads an update, it counts as one update. This model is often more cost-effective because you only pay for actual usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expo Updates Pricing
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;MAUs Included&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;1,000 MAUs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Starter&lt;/td&gt;
&lt;td&gt;$19&lt;/td&gt;
&lt;td&gt;3,000 MAUs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production&lt;/td&gt;
&lt;td&gt;$199&lt;/td&gt;
&lt;td&gt;50,000 MAUs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;$1,999&lt;/td&gt;
&lt;td&gt;1,000,000 MAUs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Overage pricing:&lt;/strong&gt; If you exceed your plan's MAU limit, Expo charges per additional MAU on a tiered scale starting at $0.005/MAU for the first 197K extra, decreasing to $0.00085/MAU at scale (100M+).&lt;/p&gt;

&lt;h3&gt;
  
  
  Turbopush Pricing
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;Releases&lt;/th&gt;
&lt;th&gt;Updates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Startup&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;50,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Growth&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Business&lt;/td&gt;
&lt;td&gt;$90&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Real-World Scenarios
&lt;/h3&gt;

&lt;p&gt;Let's analyze three realistic scenarios to see how costs compare:&lt;/p&gt;




&lt;h4&gt;
  
  
  Scenario 1: Early-Stage Startup
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;10,000 active users, 3 releases per month&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Expo Updates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10,000 MAUs exceeds Starter plan (3,000 MAUs)&lt;/li&gt;
&lt;li&gt;Starter + overage: $19 + (7,000 × $0.005) = &lt;strong&gt;$54/month&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With Turbopush:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10,000 users × 3 releases = 30,000 updates/month&lt;/li&gt;
&lt;li&gt;Startup plan includes 50,000 updates&lt;/li&gt;
&lt;li&gt;Required plan: &lt;strong&gt;Startup at $15/month&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;20,000 updates remaining&lt;/strong&gt; — room to grow or ship more releases&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Expo Updates&lt;/td&gt;
&lt;td&gt;$54&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turbopush&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Annual Savings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$468&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h4&gt;
  
  
  Scenario 2: Growing Product
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;20,000 active users, 3 releases per month&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Expo Updates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;20,000 MAUs exceeds Starter plan (3,000 MAUs)&lt;/li&gt;
&lt;li&gt;Starter + overage: $19 + (17,000 × $0.005) = &lt;strong&gt;$104/month&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;(Production at $199 would be more expensive)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With Turbopush:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;20,000 users × 3 releases = 60,000 updates/month&lt;/li&gt;
&lt;li&gt;Growth plan includes 1,000,000 updates&lt;/li&gt;
&lt;li&gt;Required plan: &lt;strong&gt;Growth at $40/month&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;940,000 updates remaining&lt;/strong&gt; — 94% headroom for growth&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Expo Updates&lt;/td&gt;
&lt;td&gt;$104&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turbopush&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Annual Savings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$768&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h4&gt;
  
  
  Scenario 3: Scaling Application
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;100,000 active users, 4 releases per month&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Expo Updates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100,000 MAUs exceeds Production plan (50,000 MAUs)&lt;/li&gt;
&lt;li&gt;Production + overage: $199 + (50,000 × $0.005) = &lt;strong&gt;$449/month&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;(Starter + overage would be $504, so Production is better)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With Turbopush:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100,000 users × 4 releases = 400,000 updates/month&lt;/li&gt;
&lt;li&gt;Growth plan includes 1,000,000 updates&lt;/li&gt;
&lt;li&gt;Required plan: &lt;strong&gt;Growth at $40/month&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;600,000 updates remaining&lt;/strong&gt; — room to 2.5x your user base&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Expo Updates&lt;/td&gt;
&lt;td&gt;$449&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turbopush&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Annual Savings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$4,908&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Why the Difference?
&lt;/h3&gt;

&lt;p&gt;The key insight is that Turbopush's generous update limits mean you're paying for actual delivery, not user count. Even when accounting for Expo's overage pricing, a scaling app with 100,000 users pushing 4 releases per month pays &lt;strong&gt;$40/month with Turbopush vs $449/month with Expo&lt;/strong&gt;—that's 91% savings.&lt;/p&gt;

&lt;p&gt;The difference becomes even more significant at scale. Turbopush's &lt;strong&gt;Business plan at $90/month&lt;/strong&gt; offers unlimited releases and updates, providing completely predictable costs regardless of how much you ship or how many users you have.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Hidden Costs: Storage &amp;amp; Bandwidth Included
&lt;/h3&gt;

&lt;p&gt;One often-overlooked aspect of OTA pricing is &lt;strong&gt;storage and bandwidth&lt;/strong&gt;. With Expo Updates and other OTA platforms, you pay extra for these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Storage:&lt;/strong&gt; $0.05 per GB after your plan's limit (20 GB on Starter, 1 TB on Production)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bandwidth:&lt;/strong&gt; $0.10 per GB after your plan's limit (10 GB on Starter, 100 GB on Production)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These costs can add up quickly, especially if your app bundles assets or you're shipping frequent updates to a large user base. A single 5 MB update to 100,000 users consumes ~500 GB of bandwidth—that's $40 in bandwidth alone on top of your base plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbopush includes storage and bandwidth in all plans.&lt;/strong&gt; No surprise charges, no metering your bundle sizes, no worrying about how many assets you're shipping. Your monthly cost is exactly what you see in your plan—nothing more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Turbopush
&lt;/h2&gt;

&lt;p&gt;Ready to add OTA updates to your React Native app? Getting started with Turbopush takes less than 30 minutes. Our step-by-step guide walks you through everything: creating your account, installing the SDK, configuring your app, and shipping your first update.&lt;/p&gt;

&lt;p&gt;Whether you're using bare React Native or Expo, we have dedicated guides for each setup.&lt;/p&gt;

&lt;p&gt;The entire setup typically takes less than 30 minutes, and the productivity gains are immediate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.turbopush.org/?utm_source=devto&amp;amp;utm_campaign=what-are-ota-updates-and-why-they-matter" rel="noopener noreferrer"&gt;Read the Getting Started Guide →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;OTA updates represent a fundamental shift in how mobile apps are developed and deployed. By decoupling your JavaScript code from app store releases, you gain the speed and flexibility that web developers have enjoyed for years.&lt;/p&gt;

&lt;p&gt;Whether you're fixing a critical bug, testing a new feature, or simply iterating faster, OTA updates remove friction from your development workflow. And with platforms like Turbopush offering generous pricing tiers, there's never been a better time to adopt this technology.&lt;/p&gt;

&lt;p&gt;The question isn't whether you should use OTA updates—it's how quickly you can get started.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Ready to ship faster?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://turbopush.org?utm_source=devto&amp;amp;utm_campaign=what-are-ota-updates-and-why-they-matter" rel="noopener noreferrer"&gt;Turbopush Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.turbopush.org?utm_source=devto&amp;amp;utm_campaign=what-are-ota-updates-and-why-they-matter" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.turbopush.org/?utm_source=devto&amp;amp;utm_campaign=what-are-ota-updates-and-why-they-matter" rel="noopener noreferrer"&gt;Getting Started Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.turbopush.org/examples/expo?utm_source=devto&amp;amp;utm_campaign=what-are-ota-updates-and-why-they-matter" rel="noopener noreferrer"&gt;Try the Live Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.turbopush.org/sign-up?utm_source=devto&amp;amp;utm_campaign=what-are-ota-updates-and-why-they-matter" rel="noopener noreferrer"&gt;Create Your Free Account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy shipping! 🚀&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>expo</category>
    </item>
    <item>
      <title>Ship Expo Updates (OTA) in Minutes: A Complete Turbopush Getting Started Guide</title>
      <dc:creator>Turbopush</dc:creator>
      <pubDate>Sun, 04 Jan 2026 14:57:45 +0000</pubDate>
      <link>https://dev.to/turbopushdev/ship-expo-updates-ota-in-minutes-a-complete-turbopush-getting-started-guide-45jk</link>
      <guid>https://dev.to/turbopushdev/ship-expo-updates-ota-in-minutes-a-complete-turbopush-getting-started-guide-45jk</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Looking for a cost-effective alternative to EAS Updates?&lt;/strong&gt; Turbopush offers the same power and flexibility at a fraction of the cost, with additional features like gradual rollouts, instant rollbacks, and detailed analytics.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Turbopush?
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Perfect for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fixes that can't wait for app store approval&lt;/li&gt;
&lt;li&gt;A/B testing new features&lt;/li&gt;
&lt;li&gt;Gradual rollouts to specific user segments&lt;/li&gt;
&lt;li&gt;Quick iterations during development&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Want to See It in Action First?
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.turbopush.org/examples/expo?utm_source=devto&amp;amp;utm_campaign=ship-expo-updates-in-minutes" rel="noopener noreferrer"&gt;Try the Live Demo →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This working example lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See how OTA updates download and install&lt;/li&gt;
&lt;li&gt;Test mandatory vs. optional updates&lt;/li&gt;
&lt;li&gt;Experience rollback functionality&lt;/li&gt;
&lt;li&gt;Check update status in real-time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Takes less than 2 minutes to try. Once you see it working, you'll know exactly what you're building!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;⚠️ Important: Turbopush does NOT work with Expo Go&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;npx expo prebuild&lt;/code&gt;,&lt;/p&gt;

&lt;p&gt;This is a one-time setup. Once you have a custom build installed on your device, OTA updates will work seamlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install the Turbopush CLI
&lt;/h2&gt;

&lt;p&gt;The Turbopush CLI is your command center for managing releases. Install it as a dev dependency in your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @turbopush/cli
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; @turbopush/cli
&lt;span class="c"&gt;# or&lt;/span&gt;
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; @turbopush/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the installation worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the CLI version printed out. If you do, you're good to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create Your Turbopush Account
&lt;/h2&gt;

&lt;p&gt;Head over to &lt;a href="https://app.turbopush.org/sign-up" rel="noopener noreferrer"&gt;https://app.turbopush.org/sign-up&lt;/a&gt; and create your free account. The process is straightforward - just your email and you're in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Authenticate the CLI
&lt;/h2&gt;

&lt;p&gt;Now let's connect your local CLI to your Turbopush account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your browser for authentication&lt;/li&gt;
&lt;li&gt;Generate a secure access key&lt;/li&gt;
&lt;li&gt;Prompt you to paste that key back in your terminal&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you see a success message, verify you're logged in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush &lt;span class="nb"&gt;whoami&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Your Default Organization
&lt;/h3&gt;

&lt;p&gt;If you're working with a team or have multiple organizations, set your default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush org &lt;span class="nb"&gt;set&lt;/span&gt; &amp;lt;your-organization-slug&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not sure what your organization slug is? List them all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush org list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Register Your Apps
&lt;/h2&gt;

&lt;p&gt;Here's an important detail: &lt;strong&gt;you need to create separate apps for iOS and Android&lt;/strong&gt;. This ensures each platform gets the right update packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush app add MyApp-iOS &lt;span class="nt"&gt;--appSlug&lt;/span&gt; myapp-ios
npx turbopush app add MyApp-Android &lt;span class="nt"&gt;--appSlug&lt;/span&gt; myapp-android
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--appSlug&lt;/code&gt; 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Save Your Deployment Keys
&lt;/h3&gt;

&lt;p&gt;After creating each app, you'll see output like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;┌────────────┬─────────────────────────────────────┐
│ Name       │ Deployment Key                      │
├────────────┼─────────────────────────────────────┤
│ Production │ dk_19ffa8fc2a91f2cd9afb3bfecafef06d │
├────────────┼─────────────────────────────────────┤
│ Staging    │ dk_5g5dc7aa6197c1f292cd12ca28f39bb3 │
└────────────┴─────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Write these keys down!&lt;/strong&gt; You'll need them in the next step. Each app gets two deployment keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Staging&lt;/strong&gt;: For testing updates before going live&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production&lt;/strong&gt;: For your production users&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Install the Turbopush SDK
&lt;/h2&gt;

&lt;p&gt;Now let's add Turbopush to your Expo project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx expo &lt;span class="nb"&gt;install&lt;/span&gt; @turbopush/react-native-code-push @turbopush/turbopush-expo-plugin expo-build-properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs three packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@turbopush/react-native-code-push&lt;/code&gt;: The core SDK&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@turbopush/turbopush-expo-plugin&lt;/code&gt;: Expo configuration plugin&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;expo-build-properties&lt;/code&gt;: To set the minimum iOS deployment target (15.5 required)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 6: Configure Your App
&lt;/h2&gt;

&lt;p&gt;Open your &lt;code&gt;app.json&lt;/code&gt; (or &lt;code&gt;app.config.js&lt;/code&gt;) and add the Turbopush configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"expo-build-properties"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"ios"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"deploymentTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"15.5"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"@turbopush/turbopush-expo-plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"android"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"CodePushDeploymentKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-android-staging-key"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"ios"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"CodePushDeploymentKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-ios-staging-key"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;your-android-staging-key&lt;/code&gt; and &lt;code&gt;your-ios-staging-key&lt;/code&gt; with the actual keys from Step 4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;expo-build-properties&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Use environment variables for deployment keys so you can easily switch between Staging and Production:&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Run Prebuild
&lt;/h2&gt;

&lt;p&gt;Before building, you need to generate the native code with prebuild:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx expo prebuild
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command generates the &lt;code&gt;ios&lt;/code&gt; and &lt;code&gt;android&lt;/code&gt; folders with all the necessary native configurations from your plugins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Integrate CodePush in Your Code
&lt;/h2&gt;

&lt;p&gt;The final code step is to wrap your app with the CodePush higher-order component. This is what checks for and downloads updates.&lt;/p&gt;

&lt;p&gt;Open your root component (usually &lt;code&gt;App.tsx&lt;/code&gt; or &lt;code&gt;App.js&lt;/code&gt;) and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;codePush&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@turbopush/react-native-code-push&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Your app code here&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Your app components&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;codePush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for the code! The &lt;code&gt;codePush()&lt;/code&gt; wrapper automatically handles checking for updates when your app starts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Want More Control?
&lt;/h3&gt;

&lt;p&gt;You can customize the update behavior by passing options directly to the &lt;code&gt;codePush()&lt;/code&gt; wrapper:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interactive updates&lt;/strong&gt; (show dialog and install immediately):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;codePush&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@turbopush/react-native-code-push&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Your app code&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Your app components&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;codePush&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="na"&gt;updateDialog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;installMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;codePush&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;InstallMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IMMEDIATE&lt;/span&gt; 
&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Custom update dialog&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;codePush&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;updateDialog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Update Available&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;optionalUpdateMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A new version is available. Install now?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;optionalInstallButtonLabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Install&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;optionalIgnoreButtonLabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Later&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;installMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;codePush&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;InstallMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IMMEDIATE&lt;/span&gt;
&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 9: Build and Run Your App
&lt;/h2&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For iOS (simulator or device) - Release mode&lt;/span&gt;
npx expo run:ios &lt;span class="nt"&gt;--configuration&lt;/span&gt; Release

&lt;span class="c"&gt;# For Android (emulator or device) - Release mode&lt;/span&gt;
npx expo run:android &lt;span class="nt"&gt;--variant&lt;/span&gt; release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; We're using &lt;code&gt;--configuration Release&lt;/code&gt; (iOS) and &lt;code&gt;--variant release&lt;/code&gt; (Android) to build in production mode. This ensures the app behaves exactly like it will in production with OTA updates enabled.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10: Release Your First Update
&lt;/h2&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;Then release it to Turbopush using the Expo-specific command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For iOS (replace "1.0.0" with your app version)&lt;/span&gt;
npx turbopush release-expo myapp-ios ios &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;

&lt;span class="c"&gt;# For Android&lt;/span&gt;
npx turbopush release-expo myapp-android android &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bundle your JavaScript code using Expo's bundler&lt;/li&gt;
&lt;li&gt;Upload it to Turbopush&lt;/li&gt;
&lt;li&gt;Make it available to your app immediately&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; The version number (&lt;code&gt;"1.0.0"&lt;/code&gt;) must match exactly what's in your &lt;code&gt;app.json&lt;/code&gt; under &lt;code&gt;expo.version&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Release with Options
&lt;/h3&gt;

&lt;p&gt;You can customize your release with additional parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush release-expo myapp-ios ios &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--deploymentName&lt;/span&gt; &lt;span class="s2"&gt;"Production"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Critical bug fixes"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--mandatory&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rollout&lt;/span&gt; 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--deploymentName&lt;/code&gt; or &lt;code&gt;-d&lt;/code&gt;: Target deployment (default: "Staging")&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--description&lt;/code&gt; or &lt;code&gt;--des&lt;/code&gt;: Release notes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--mandatory&lt;/code&gt; or &lt;code&gt;-m&lt;/code&gt;: Force users to install this update&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--rollout&lt;/code&gt; or &lt;code&gt;-r&lt;/code&gt;: Gradual rollout percentage (e.g., 25 = 25% of users)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 11: Test Your Update
&lt;/h2&gt;

&lt;p&gt;Open your app on the test device. You should see one of these scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Immediate update (mandatory)&lt;/strong&gt;: If your app was closed, it downloads and applies the update on restart&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Background update (non-mandatory)&lt;/strong&gt;: If your app was running, it downloads the update and applies it on the next restart&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Check your device logs to see the update process in action. You should see messages about checking for updates, downloading, and installing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues and Quick Fixes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  No updates available
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Double-check your deployment keys are correct&lt;/li&gt;
&lt;li&gt;Verify you're targeting the right deployment (Staging vs Production)&lt;/li&gt;
&lt;li&gt;Make sure your app version matches the release target version&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Binary version mismatch
&lt;/h3&gt;

&lt;p&gt;Your release target version must match exactly what's in your &lt;code&gt;app.json&lt;/code&gt;. If your app is &lt;code&gt;1.0.0&lt;/code&gt;, release to &lt;code&gt;1.0.0&lt;/code&gt;, not &lt;code&gt;1.0.1&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updates not installing
&lt;/h3&gt;

&lt;p&gt;Make sure &lt;code&gt;codePush()&lt;/code&gt; is wrapping your root component. The wrapper is what enables the update functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Congratulations! You've successfully set up Turbopush and pushed your first OTA update. Here are some things to explore next:&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Deployment Strategy
&lt;/h3&gt;

&lt;p&gt;Use Staging for testing and Production for live users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Test on staging first&lt;/span&gt;
npx turbopush release-expo myapp-ios ios &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; Staging

&lt;span class="c"&gt;# Once verified, promote to production&lt;/span&gt;
npx turbopush promote myapp-ios Staging Production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Monitor Your Releases
&lt;/h3&gt;

&lt;p&gt;Check your deployment history and see how users are adopting updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx turbopush deployment &lt;span class="nb"&gt;history &lt;/span&gt;myapp-ios Production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manage Updates via Dashboard
&lt;/h3&gt;

&lt;p&gt;While the CLI is powerful, you can also manage and monitor everything through the Turbopush web dashboard at &lt;a href="https://app.turbopush.org" rel="noopener noreferrer"&gt;https://app.turbopush.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The dashboard gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visual deployment history&lt;/strong&gt;: See all your releases with timestamps, descriptions, and rollout percentages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time metrics&lt;/strong&gt;: Track how many users have downloaded and installed each update&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version distribution&lt;/strong&gt;: See which versions your users are running&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy rollbacks&lt;/strong&gt;: Rollback problematic updates with a single click&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team collaboration&lt;/strong&gt;: Manage team access and permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced Update Strategies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mandatory updates&lt;/strong&gt;: Force users to install critical fixes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradual rollouts&lt;/strong&gt;: Release to 10% of users, then 50%, then 100%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target specific versions&lt;/strong&gt;: Send different updates to different app versions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Turbopush?
&lt;/h2&gt;

&lt;p&gt;If you've used other OTA update solutions, here's what makes Turbopush different:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost-Effective Alternative to EAS Updates&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;100% CodePush Compatible&lt;/strong&gt;: Drop-in replacement for AppCenter CodePush. No code changes needed - just update your deployment keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Universal Platform Support&lt;/strong&gt;: Works with bare React Native, Expo, and the New Architecture (Fabric + TurboModules).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rich Analytics Dashboard&lt;/strong&gt;: Track install rates, version adoption, rollback events, and detailed user metrics in real-time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Affordable Pricing&lt;/strong&gt;: Pay-as-you-grow with a generous free tier. Significantly more cost-effective than EAS Updates without compromising features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advanced Features&lt;/strong&gt;: Gradual rollouts, instant rollbacks, version targeting, mandatory updates, and delta updates for minimal bandwidth usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modern Developer Experience&lt;/strong&gt;: Beautiful CLI, TypeScript SDK, comprehensive docs, and excellent support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Want to learn more? Check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://turbopush.org?utm_source=devto&amp;amp;utm_campaign=ship-expo-updates-in-minutes" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.turbopush.org?utm_source=devto&amp;amp;utm_campaign=ship-expo-updates-in-minutes" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.turbopush.org/getting-started?utm_source=devto&amp;amp;utm_campaign=ship-expo-updates-in-minutes" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.turbopush.org/examples/expo?utm_source=devto&amp;amp;utm_campaign=ship-expo-updates-in-minutes" rel="noopener noreferrer"&gt;Example Apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy shipping! 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found this helpful? Leave a comment and follow for more React Native and Expo tutorials.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
