{"id":14761,"date":"2024-10-28T14:43:39","date_gmt":"2024-10-28T13:43:39","guid":{"rendered":"https:\/\/pagepro.co\/blog\/?p=14761"},"modified":"2026-01-28T11:26:01","modified_gmt":"2026-01-28T10:26:01","slug":"ota-updates-with-expo","status":"publish","type":"post","link":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/","title":{"rendered":"OTA Updates With Expo"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\" id=\"what-is-an-ota-update\">What is an OTA update?<\/h2>\n\n\n\n<p>Over-the-air (OTA) are\u2026 updates that are sent over the air. Yeah, I know that does not explain anything but bear with me. Expo OTA updates are <strong>a fantastic method to swiftly fix your application without the usual delays<\/strong>. It enables you to bypass the App Store or Google Play store entirely when releasing an update.<\/p>\n\n\n\n<p>Imagine that your mobile app has a critical bug in production and releasing a fix can take days to reach your customers. Even if it&#8217;s a quick fix, <strong>each update released to the App Store or Google Play has to go through a store review process before it\u2019s approved<\/strong>.&nbsp;<\/p>\n\n\n\n<p>This process can be a bit of a pain, especially because it can be time-consuming and sometimes costly, and let&#8217;s face it, every hour counts because you don&#8217;t want to miss out on potential users just because your app isn&#8217;t working as it should. This is where Expo&#8217;s over-the-air update function comes in handy for all mobile app developers.<\/p>\n\n\n\n<p><strong><a href=\"https:\/\/pagepro.co\/services\/expo-development\" target=\"_blank\" rel=\"noreferrer noopener\">Expo<\/a> OTA updates let you send critical bug fixes immediately without even worrying about verification times<\/strong>, which helps to improve user experience!<\/p>\n\n\n\n<p><strong>It is a feature exclusive to<\/strong> <strong><a href=\"https:\/\/pagepro.co\/services\/react-native-development\" target=\"_blank\" rel=\"noreferrer noopener\">React Native mobile applications<\/a><\/strong> because of its unique functionality. They comprise two key components: native code and the JS bundle. The JS bundle, which contains about <strong>90% of the application logic<\/strong>, can be completely replaced using OTA updates.<\/p>\n\n\n\n<p>Interested? <strong>Let&#8217;s implement OTA in your Expo app<\/strong>!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"creating-a-new-expo-application\">Creating a New Expo Application<\/h2>\n\n\n\n<p>First, let&#8217;s start with <strong>creating a new Expo application.<\/strong> To do this, simply run this command in the terminal where \u201cmy-app\u201d will be the name of your application.<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\">npx create-expo-app my-app<\/code><\/pre>\n\n\n\n<p>This will create a new project for us and install all necessary dependencies to run the application. To test if it works it can be opened by running.<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\"># go to the project directory\ncd my-app\n\n# for android\nnpm run android\n\n# for ios\nnpm run ios<\/code><\/pre>\n\n\n\n<p>You should be seeing an app like this:<\/p>\n\n\n<div class=\"wp-block-image is-resized\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"407\" height=\"719\" src=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3.png\" alt=\"OTA Welcome Screen\" class=\"wp-image-18291\" srcset=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3.png 407w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-170x300.png 170w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-189x334.png 189w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-324x572.png 324w\" sizes=\"(max-width: 407px) 100vw, 407px\" \/><\/figure><\/div>\n\n\n<p><\/p>\n\n\n\n<p>The next step is to create a new application on <a href=\"https:\/\/expo.dev\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">https:\/\/expo.dev<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"573\" src=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2-1024x573.png\" alt=\"OTA create project\n\" class=\"wp-image-14763\" srcset=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2-1024x573.png 1024w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2-300x168.png 300w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2-768x430.png 768w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2-1536x859.png 1536w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2-500x280.png 500w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2-324x181.png 324w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/image2.png 1999w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And then link it to our local application by running the command shown on the screen:<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\">\nnpm install --global eas-cli &amp;&amp; \\\neas init --id &lt;id_of_your_project>\n<\/code><\/pre>\n\n\n\n<p>With this, we are ready to add OTA updates to our app!<\/p>\n\n\n\n<div class=\"wp-block-code-mind-cta c-cta-block\" style=\"background-color:#00141F;color:#FFFFFF\"><div class=\"c-cta-block__content\"><p class=\"c-cta-block__title\">Not sure where to start with your mobile app?<\/p><div class=\"c-cta-block__action\"><a href=\"https:\/\/pagepro.co\/contact\" class=\"c-cta-block__button ga-cta ga-cta-consultation theme-bg-3\">Have a chat with us<\/a><\/div><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"adding-ota-feature-to-the-expo-app\">Adding OTA Feature to the Expo App<\/h2>\n\n\n\n<p>First, we need to install the expo-updates library and then configure both EAS build and updates to work properly. This can be done with the following commands (please run the commands in the provided order).<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\">npx expo install expo-updates\neas build:configure\neas update:configure<\/code><\/pre>\n\n\n\n<p>After running these commands you should see some changes made to your project. The file that interests us the most is the eas.json file, it should look something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"json\">{\n \"cli\": {\n   \"version\": \">= 11.0.2\"\n },\n \"build\": {\n   \"development\": {\n     \"developmentClient\": true,\n     \"distribution\": \"internal\",\n     \"channel\": \"development\"\n   },\n   \"preview\": {\n     \"distribution\": \"internal\",\n     \"channel\": \"preview\"\n   },\n   \"production\": {\n     \"channel\": \"production\"\n   }\n },\n \"submit\": {\n   \"production\": {}\n }\n}\n<\/code><\/pre>\n\n\n\n<p>This file contains the profiles for each of our build profiles. Running the \u201c<code>eas update:configure<\/code>\u201d command has added a \u201cchannel\u201d key for our profiles. This key allows us to which profile receives specific updates for our app. Don&#8217;t worry, we&#8217;ll dig into the details of channels shortly. First, let\u2019s check if our updates work!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"pushing-the-first-update\">Pushing the First Update<\/h2>\n\n\n\n<p>Before we can check if our updates work we have to build a standalone version of our app as development or Expo Go builds are designed to always load the latest available bundle.<br><\/p>\n\n\n\n<p>We will create a build with the \u201cpreview\u201d profile which by default is intended for internal distribution to showcase the application. To do this run the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\">eas build --profile preview --platform android<\/code><\/pre>\n\n\n\n<p>After the build is completed you can download it on <a href=\"https:\/\/expo.dev\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">https:\/\/expo.dev<\/a> under the \u201cbuilds\u201d page. You can either install it on your real device by using the QR code shown after pressing the \u201cInstall\u201d button or download an apk file by pressing the options -&gt; download build and drag it onto your simulator.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"486\" src=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2-1024x486.png\" alt=\"Expo Dashboard View\n\" class=\"wp-image-18292\" srcset=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2-1024x486.png 1024w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2-300x142.png 300w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2-768x364.png 768w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2-1536x728.png 1536w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2-500x237.png 500w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2-324x154.png 324w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image2.png 1999w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>As you launch the application you will notice one major difference right away: the absence of the Expo Go client. Your app is built in a standalone version which looks and behaves like a production version of your application. But just like before you will see the same screen as we had originally in our app saying \u201cOpen up App.js to start working on your app!\u201d<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img decoding=\"async\" loading=\"lazy\" width=\"407\" height=\"719\" src=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-1.png\" alt=\"OTA Welcome Screen\n\" class=\"wp-image-18293\" srcset=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-1.png 407w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-1-170x300.png 170w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-1-189x334.png 189w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image3-1-324x572.png 324w\" sizes=\"(max-width: 407px) 100vw, 407px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Let&#8217;s now make a change and push it to our already-built app! Open the \u201cApp.js\u201d file and change the Welcome text to <code>I\u2019m from an OTA update!<\/code> <\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\">import { Image, StyleSheet, Platform } from 'react-native'\n\n\nimport { HelloWave } from '@\/components\/HelloWave'\nimport ParallaxScrollView from '@\/components\/ParallaxScrollView'\nimport { ThemedText } from '@\/components\/ThemedText'\nimport { ThemedView } from '@\/components\/ThemedView'\n\n\nexport default function HomeScreen() {\n return (\n   &lt;ParallaxScrollView\n     headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}\n     headerImage={\n       &lt;Image\n         source={require('@\/assets\/images\/partial-react-logo.png')}\n         style={styles.reactLogo}\n       \/>\n     }\n   >\n     &lt;ThemedView style={styles.titleContainer}>\n       &lt;ThemedText type=\"title\">I\u2019m from an OTA update!&lt;\/ThemedText>\n       &lt;HelloWave \/>\n     &lt;\/ThemedView>\n    . . .\n<\/code><\/pre>\n\n\n\n<p>We can easily preview the changes that we have made by running \u201cnpm run android\u201d but these are only visible to us. To push this change to all users who have installed our app in the \u201cpreview\u201d channel we have to run this command:<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\">eas update --branch preview --message \"Example update\"<\/code><\/pre>\n\n\n\n<p>This command will create a new js bundle with the changes we have made and send it to expo servers so it is available for our users. The \u201cmessage\u201d argument is a short description of our update. We will discuss the \u201cbranch\u201d argument later together with channels.<\/p>\n\n\n<div class=\"c-newsletter-sendgrid-wrapper js-newsletter-sendgrid-wrapper ga-filedownload-viewed\">\n    <div class=\"c-newsletter-sendgrid\">\n                    <p class=\"c-newsletter-sendgrid__title\">\n                Get Your Essential Checklist for Publishing Expo React Native Apps            <\/p>\n        \n         \n            <p class=\"c-newsletter-sendgrid__description\">\n                A step-by-step guide to deploying apps with confidence and ease.            <\/p>\n        \n        <form action=\"\" class=\"c-newsletter-sendgrid__form f-form js-newsletter-sendgrid\" data-key=\"b59fc663-b9b3-465f-8d97-58e1b3636234\">\n            <div class=\"c-newsletter-sendgrid__form-mail\">\n                <label class=\"c-label\" for=\"newsletter_email\">Company E-mail address<\/label>\n                <input class=\"c-input js-newsletter-sendgrid-email\" type=\"email\" id=\"newsletter_email\" required>\n                <input class=\"c-newsletter-sendgrid__button ga-cta-filedownload\" type=\"submit\" value=\"Download Now\">\n            <\/div>\n            <div class=\"c-newsletter-sendgrid__form-consent\">\n                                                        <input class=\"c-checkbox js-newsletter-consent\" type=\"checkbox\" name=\"newsletter_consent\" id=\"newsletter_consent_1\" required>\n                    <label class=\"c-label\" for=\"newsletter_consent_1\">By providing your e-mail address, you agree to our Privacy Policy. We will not send you any spam \u2013 only link for downloading the e-book and probably some more useful resources in the future.<\/label>\n                            <\/div>\n        <\/form>\n\n        <div class=\"c-newsletter-sendgrid__cover-container\">\n                            <img decoding=\"async\" class=\"c-newsletter-sendgrid__cover-1\" src=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/08\/Ebook-Expo-React-Native.png\" alt=\"Cover image with red and black geometric shapes, the Pagepro logo, and white text: Publishing Expo App React Native\u2014Your Essential Checklist.\" >\n                                            <\/div>\n\n        <div class=\"c-newsletter-sendgrid__popup-wrapper js-newsletter-sendgrid-popup is-hidden\">\n            <div class=\"c-newsletter-sendgrid__popup\">\n                <div class=\"c-newsletter-sendgrid__popup-icon\">\n                    <svg width=\"140\" height=\"140\" viewBox=\"0 0 140 140\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                    <g clip-path=\"url(#clip0_6621_2135)\">\n                    <path d=\"M65.625 100.625C65.625 109.908 69.3125 118.81 75.8763 125.374C82.44 131.938 91.3424 135.625 100.625 135.625C109.908 135.625 118.81 131.938 125.374 125.374C131.938 118.81 135.625 109.908 135.625 100.625C135.625 91.3424 131.938 82.44 125.374 75.8763C118.81 69.3125 109.908 65.625 100.625 65.625C91.3424 65.625 82.44 69.3125 75.8763 75.8763C69.3125 82.44 65.625 91.3424 65.625 100.625Z\" stroke=\"#0A2B3D\" stroke-width=\"8.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n                    <path d=\"M116.223 90.4517L99.2774 113.044C98.9005 113.545 98.4206 113.959 97.8701 114.259C97.3196 114.558 96.7113 114.737 96.0862 114.781C95.461 114.826 94.8335 114.736 94.246 114.518C93.6584 114.3 93.1244 113.959 92.6799 113.517L83.9299 104.767\" stroke=\"#0A2B3D\" stroke-width=\"8.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n                    <path d=\"M48.125 91.875H13.125C10.8044 91.875 8.57876 90.9531 6.93782 89.3122C5.29687 87.6712 4.375 85.4456 4.375 83.125V13.125C4.375 10.8044 5.29687 8.57876 6.93782 6.93782C8.57876 5.29687 10.8044 4.375 13.125 4.375H118.125C120.446 4.375 122.671 5.29687 124.312 6.93782C125.953 8.57876 126.875 10.8044 126.875 13.125V52.5\" stroke=\"#0A2B3D\" stroke-width=\"8.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n                    <path d=\"M124.898 7.5835L77.3909 44.1235C74.0176 46.7185 69.881 48.1255 65.625 48.1255C61.3691 48.1255 57.2325 46.7185 53.8592 44.1235L6.35254 7.5835\" stroke=\"#0A2B3D\" stroke-width=\"8.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n                    <\/g>\n                    <defs>\n                    <clipPath id=\"clip0_6621_2135\">\n                    <rect width=\"140\" height=\"140\" fill=\"white\"\/>\n                    <\/clipPath>\n                    <\/defs>\n                    <\/svg>\n                <\/div>\n                                    <p class=\"c-newsletter-sendgrid__popup-text\">\n                        Check your inbox for free materials                    <\/p>\n                                <div class=\"c-newsletter-sendgrid__popup-action\">\n                    <button class=\"c-newsletter-sendgrid__button c-newsletter-sendgrid__button--full-width js-newsletter-sendgrid-popup-close\">Close<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"lets-check-our-expo-ota-update\">Let\u2019s Check our Expo OTA Update!<\/h2>\n\n\n\n<p>Open the standalone app we have installed previously on the device and\u2026 there are no changes. Why is that? Let me explain.<br><br>The default behaviour of expo-updates is to check for available updates at every app launch. If there are any updates available the newest of them is downloaded in the background while the app is running without the user even noticing it. <\/p>\n\n\n\n<p>But the app is not waiting for the updates to download before showing the user the app nor is it reloaded when the update is downloaded (but it can do that if you want). <\/p>\n\n\n\n<p>By default, after the update is downloaded the user will be able to see the updated version of the app on the next launch. Go on and check it! After you restart the app you should see the changes!<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img decoding=\"async\" loading=\"lazy\" width=\"405\" height=\"716\" src=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image1.png\" alt=\"OTA Update view\n\" class=\"wp-image-18294\" srcset=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image1.png 405w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image1-170x300.png 170w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image1-189x334.png 189w, https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2024\/10\/image1-324x573.png 324w\" sizes=\"(max-width: 405px) 100vw, 405px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Do keep in mind that you have to keep the app running for a couple of seconds before restarting so it has enough time to download the update.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"but-what-about-these-channels-and-branches\">But What About These Channels and Branches?<\/h2>\n\n\n\n<p>Right, right, channels and branches. As I said before these are used to control which \u201cprofile\u201d of our app will receive specific updates. A build profile is always tied with a channel, and you can see this in the eas.json file. Each time you want to change the channel for a particular profile you will have to create a new build of the application.<br><br>On the other hand, there are the updates we make. They are always tied to a \u201cbranch\u201d. When we want to push an update to a specific channel we have to link that channel to our branch. We can do this by running this command:<\/p>\n\n\n\n<pre class=\"wp-block-code-mind-code c-code\"><code class=\"javascript\">eas channel:edit production --branch version-2.0<\/code><\/pre>\n\n\n\n<p>We didn\u2019t have to do that in our case because we named our branch the same as our channel. By default, channels are linked to branches with the same name.<br><br>So what does this additional layer give us? Flexibility! Let&#8217;s say that you push an update so your internal testing team can check it and you name your branch \u201cfix-1234\u201d. After the testing is done and the fix is confirmed you don\u2019t have to do another push to your production channel.&nbsp;<\/p>\n\n\n\n<p>Simply link your production channel to the \u201cfix-1234\u201d branch and your users will start receiving the update! Doing it this way ensures that no potential changes will be included in the production update and the deployed code is the same as the one verified by testers.<\/p>\n\n\n\n<p>And that\u2019s it! But\u2026there are things to consider.<\/p>\n\n\n\n<div class=\"c-newsletter-block-acf\">\n    <p class=\"c-newsletter-block-acf__title c-newsletter__header\">\n        EXPERT INSIGHTS, FRICTIONLESSLY DELIVERED!    <\/p>\n    <p class=\"c-newsletter-block-acf__desc c-newsletter__header\">\n        Curated tech news delivered straight to your inbox every month.\r\n    <\/p>\n    <form method=\"post\" class=\"c-newsletter-block-acf__form js-newsletter-form c-newsletter__action\" name=\"newsletter-block-form\">\n        <input name=\"newsletter-email\" id=\"newsletter-email\" type=\"text\" class=\"c-newsletter-block-acf__input js-newsletter-input\" placeholder=\"Company Email\" \/>\n        <input name=\"newsletter-campaign\" id=\"newsletter-campaign\" type=\"hidden\" value=\"\" \/>\n        <div class=\"c-newsletter-block-acf__group\">\n            <input name=\"consent\" id=\"consent\" type=\"checkbox\" class=\"js-newsletter-consent\" \/>\n            <label class=\"c-newsletter-block-acf__label\" for=\"consent\">I accept the <a href=\"https:\/\/pagepro.co\/privacy-policy\">Privacy Policy<\/a> and agree to process my personal data by Pagepro for marketing purposes.<\/label>\n        <\/div>\n        <input type=\"submit\" class=\"c-newsletter-block-acf__button button js-newsletter-sub ga-newsletter-form-content\" value=\"Sign up\" \/>\n        <p class=\"theme-size-1 js-message-valid is-hidden is-invalid\"><\/p>\n    <\/form>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"things-to-keep-in-mind-about-expo-ota-updates\">Things to Keep in Mind About Expo OTA Updates<\/h2>\n\n\n\n<p><br>While OTA updates may seem to be the best way to deliver updates to your app they cannot be used in all scenarios.<\/p>\n\n\n\n<p>Firstly, <strong>if you make any changes to the native code, OTA updates won&#8217;t work<\/strong>. Remember, Expo OTA updates solely update the JS bundle and not the native code. Pushing an OTA update with native changes can potentially break the app for end users since the JS code may reference native modules that can not exist.<\/p>\n\n\n\n<p>To ensure that your users always receive the correct updates for their native app version you can use the \u201c<code>expo.runtimeVersion<\/code>\u201d key located in \u201c<code>app.json<\/code>\u201d file. <strong>Make sure to update its value<\/strong> before making any changes to the native Android and iOS code and pushing the update.<\/p>\n\n\n\n<p>Secondly, <strong><strong>you shouldn\u2019t implement new features with over-the-air updates<\/strong><\/strong>, because such changes omit Apple and Google verification. Expo OTA updates are typically meant to publish bug fixes that will later be included in the base application published in the respective app stores.<\/p>\n\n\n\n<p>Happy coding!<\/p>\n\n\n\n<div class=\"wp-block-code-mind-cta c-cta-block\" style=\"background-color:#00141F;color:#FFFFFF\"><div class=\"c-cta-block__content\"><p class=\"c-cta-block__title\">Ready to start using OTA updates in your React Native App?<\/p><div class=\"c-cta-block__action\"><a href=\"https:\/\/pagepro.co\/contact\" class=\"c-cta-block__button ga-cta ga-cta-consultation theme-bg-3\">Talk to our experts<\/a><\/div><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"read-more\">Read More <\/h2>\n\n\n\n<p><a href=\"https:\/\/pagepro.co\/blog\/what-is-expo-js\/\" target=\"_blank\" rel=\"noreferrer noopener\">What is Expo?<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/pagepro.co\/blog\/migrating-native-app-to-react-native-with-expo\/\">Migrating a Native App to React Native? Here\u2019s How Expo Can Help<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/pagepro.co\/blog\/expo-apps\/\" target=\"_blank\" rel=\"noreferrer noopener\">40 Best Examples of Expo Apps<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/pagepro.co\/blog\/how-to-quit-expo-app-ios-android\/\" target=\"_blank\" rel=\"noreferrer noopener\">How to Quit Expo App Completely From iOS And Android?<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/pagepro.co\/blog\/publishing-expo-react-native-app-to-ios-and-android\/\" target=\"_blank\" rel=\"noreferrer noopener\">How to Publish Expo React Native App to iOS and Android?<\/a><\/p>\n\n\n\n<p> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>What is an OTA update? Over-the-air (OTA) are\u2026 updates that are sent over the air. Yeah, I know that does not explain anything but bear with me. Expo OTA updates are a fantastic method to swiftly fix your application without the usual delays. It enables you to bypass the App Store or Google Play store [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":18289,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[672,94],"tags":[503,641],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>OTA Updates with Expo: How They Work + Best Practices | Pagepro<\/title>\n<meta name=\"description\" content=\"Master Expo OTA updates: deliver instant React Native app changes without resubmitting to stores. Guide + best practices for developers.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"OTA Updates with Expo: How They Work + Best Practices | Pagepro\" \/>\n<meta property=\"og:description\" content=\"Master Expo OTA updates: deliver instant React Native app changes without resubmitting to stores. Guide + best practices for developers.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/\" \/>\n<meta property=\"og:site_name\" content=\"Pagepro\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/thisispagepro\" \/>\n<meta property=\"article:published_time\" content=\"2024-10-28T13:43:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-01-28T10:26:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/OTA-Updates-With-Expo.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"582\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Micha\u0142 Moroz\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Micha\u0142 Moroz\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/\"},\"author\":{\"name\":\"Micha\u0142 Moroz\",\"@id\":\"https:\/\/pagepro.co\/blog\/#\/schema\/person\/3ae37e87531f0c00fc5335d40895a20d\"},\"headline\":\"OTA Updates With Expo\",\"datePublished\":\"2024-10-28T13:43:39+00:00\",\"dateModified\":\"2026-01-28T10:26:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/\"},\"wordCount\":1462,\"publisher\":{\"@id\":\"https:\/\/pagepro.co\/blog\/#organization\"},\"keywords\":[\"expo\",\"ota updates\"],\"articleSection\":[\"Expo\",\"React Native\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/\",\"url\":\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/\",\"name\":\"OTA Updates with Expo: How They Work + Best Practices | Pagepro\",\"isPartOf\":{\"@id\":\"https:\/\/pagepro.co\/blog\/#website\"},\"datePublished\":\"2024-10-28T13:43:39+00:00\",\"dateModified\":\"2026-01-28T10:26:01+00:00\",\"description\":\"Master Expo OTA updates: deliver instant React Native app changes without resubmitting to stores. Guide + best practices for developers.\",\"breadcrumb\":{\"@id\":\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/pagepro.co\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\/\/pagepro.co\/blog\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"OTA Updates With Expo\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/pagepro.co\/blog\/#website\",\"url\":\"https:\/\/pagepro.co\/blog\/\",\"name\":\"Pagepro\",\"description\":\"Frictionless Next.js, Expo &amp; Sanity Development Blog\",\"publisher\":{\"@id\":\"https:\/\/pagepro.co\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/pagepro.co\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/pagepro.co\/blog\/#organization\",\"name\":\"Pagepro\",\"url\":\"https:\/\/pagepro.co\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/pagepro.co\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2020\/08\/logo_pagepro-b66d228a1e-1.png\",\"contentUrl\":\"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2020\/08\/logo_pagepro-b66d228a1e-1.png\",\"width\":440,\"height\":200,\"caption\":\"Pagepro\"},\"image\":{\"@id\":\"https:\/\/pagepro.co\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/thisispagepro\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/pagepro.co\/blog\/#\/schema\/person\/3ae37e87531f0c00fc5335d40895a20d\",\"name\":\"Micha\u0142 Moroz\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/pagepro.co\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/80639c9670393035ea3f9377162ab1a2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/80639c9670393035ea3f9377162ab1a2?s=96&d=mm&r=g\",\"caption\":\"Micha\u0142 Moroz\"},\"description\":\"Joining Pagepro in 2018, he excel in front-end development, showcasing his proficiency and passion for creating engaging, user-centric web applications. In the beginning of 2022, Micha\u0142 transitioned to the role of a React Native Developer at Pagepro, marking a significant shift in his career path. This shift is driven by a desire to leverage his front-end expertise in a more dynamic and rapidly evolving environment, focusing on building cross-platform mobile applications.\",\"url\":\"https:\/\/pagepro.co\/blog\/author\/michal-moroz\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"OTA Updates with Expo: How They Work + Best Practices | Pagepro","description":"Master Expo OTA updates: deliver instant React Native app changes without resubmitting to stores. Guide + best practices for developers.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/","og_locale":"en_US","og_type":"article","og_title":"OTA Updates with Expo: How They Work + Best Practices | Pagepro","og_description":"Master Expo OTA updates: deliver instant React Native app changes without resubmitting to stores. Guide + best practices for developers.","og_url":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/","og_site_name":"Pagepro","article_publisher":"https:\/\/www.facebook.com\/thisispagepro","article_published_time":"2024-10-28T13:43:39+00:00","article_modified_time":"2026-01-28T10:26:01+00:00","og_image":[{"width":1024,"height":582,"url":"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2023\/06\/OTA-Updates-With-Expo.png","type":"image\/png"}],"author":"Micha\u0142 Moroz","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Micha\u0142 Moroz","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/#article","isPartOf":{"@id":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/"},"author":{"name":"Micha\u0142 Moroz","@id":"https:\/\/pagepro.co\/blog\/#\/schema\/person\/3ae37e87531f0c00fc5335d40895a20d"},"headline":"OTA Updates With Expo","datePublished":"2024-10-28T13:43:39+00:00","dateModified":"2026-01-28T10:26:01+00:00","mainEntityOfPage":{"@id":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/"},"wordCount":1462,"publisher":{"@id":"https:\/\/pagepro.co\/blog\/#organization"},"keywords":["expo","ota updates"],"articleSection":["Expo","React Native"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/","url":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/","name":"OTA Updates with Expo: How They Work + Best Practices | Pagepro","isPartOf":{"@id":"https:\/\/pagepro.co\/blog\/#website"},"datePublished":"2024-10-28T13:43:39+00:00","dateModified":"2026-01-28T10:26:01+00:00","description":"Master Expo OTA updates: deliver instant React Native app changes without resubmitting to stores. Guide + best practices for developers.","breadcrumb":{"@id":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/pagepro.co\/blog\/ota-updates-with-expo\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/pagepro.co\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/pagepro.co\/blog\/"},{"@type":"ListItem","position":3,"name":"OTA Updates With Expo"}]},{"@type":"WebSite","@id":"https:\/\/pagepro.co\/blog\/#website","url":"https:\/\/pagepro.co\/blog\/","name":"Pagepro","description":"Frictionless Next.js, Expo &amp; Sanity Development Blog","publisher":{"@id":"https:\/\/pagepro.co\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/pagepro.co\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/pagepro.co\/blog\/#organization","name":"Pagepro","url":"https:\/\/pagepro.co\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/pagepro.co\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2020\/08\/logo_pagepro-b66d228a1e-1.png","contentUrl":"https:\/\/pagepro.co\/blog\/wp-content\/uploads\/2020\/08\/logo_pagepro-b66d228a1e-1.png","width":440,"height":200,"caption":"Pagepro"},"image":{"@id":"https:\/\/pagepro.co\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/thisispagepro"]},{"@type":"Person","@id":"https:\/\/pagepro.co\/blog\/#\/schema\/person\/3ae37e87531f0c00fc5335d40895a20d","name":"Micha\u0142 Moroz","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/pagepro.co\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/80639c9670393035ea3f9377162ab1a2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/80639c9670393035ea3f9377162ab1a2?s=96&d=mm&r=g","caption":"Micha\u0142 Moroz"},"description":"Joining Pagepro in 2018, he excel in front-end development, showcasing his proficiency and passion for creating engaging, user-centric web applications. In the beginning of 2022, Micha\u0142 transitioned to the role of a React Native Developer at Pagepro, marking a significant shift in his career path. This shift is driven by a desire to leverage his front-end expertise in a more dynamic and rapidly evolving environment, focusing on building cross-platform mobile applications.","url":"https:\/\/pagepro.co\/blog\/author\/michal-moroz\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/posts\/14761"}],"collection":[{"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/comments?post=14761"}],"version-history":[{"count":22,"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/posts\/14761\/revisions"}],"predecessor-version":[{"id":19022,"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/posts\/14761\/revisions\/19022"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/media\/18289"}],"wp:attachment":[{"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/media?parent=14761"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/categories?post=14761"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pagepro.co\/blog\/wp-json\/wp\/v2\/tags?post=14761"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}