Create your own
Lesson illustration

OTA Update Restrictions

Welcome to the next stage of our journey. Having successfully integrated native functionalities like filesystem access and biometrics, we are now shifting our focus from initial development to long-term maintenance and agility. Your goal of implementing Over-the-Air (OTA) updates is a key part of this, as it promises the ability to deploy changes rapidly.

This lesson marks the beginning of our module on OTA updates. Before we write any code to implement an OTA service, it's absolutely essential to understand the rules of the game. Both Apple and Google have specific policies that govern what you can and cannot change without a formal store review. This lesson is dedicated to explaining these policies, ensuring that when you do push an update, you do so with confidence and in full compliance.

1. The Core Principle of OTA Updates in Capacitor

Given your experience with React Native, you're likely familiar with the concept of shipping JavaScript bundle updates via services like CodePush. Capacitor's OTA mechanism operates on a very similar principle, which is rooted in the hybrid architecture we discussed in our first lesson.

A Capacitor application consists of two distinct layers:

  • The Native Layer: The compiled Swift/Kotlin code, which includes the Capacitor runtime and any native plugins you've installed. This code is part of the binary (.ipa or .aab file) submitted to the app stores.
  • The Web Layer: Your React application, bundled into static HTML, CSS, and JavaScript files. These assets are packaged with the app but are loaded into a WebView at runtime.

OTA updates can only change the web layer. You cannot add, remove, or update native plugins, change native configurations (Info.plist or build.gradle), or modify any compiled Swift or Kotlin code via an OTA update. Any changes to the native layer require a new binary to be submitted for store review.

The process is conceptually straightforward, as illustrated below. The app checks a server for a newer version of the web assets, downloads them if available, and then loads the new assets the next time it starts.

This diagram shows the basic flow of an OTA update: the app queries a remote server, and if an update is found, it downloads the new JavaScript bundle to be used on the next launch.

To reinforce this fundamental limitation, please watch this brief segment from a video by Coding Technyks discussing Capawesome's live update plugin.

Explore Capawesome's New Ionic Capacitor Live Update Plugin: Features & How to Get Started

This video discusses an OTA plugin for Capacitor. The presenter clearly explains the distinction between what can and cannot be updated.

Watch the section from this explanation where the host clarifies that only the web layer (HTML, CSS, JS) can be updated, and native plugins cannot be changed via this method. This is a universal rule for OTA updates, not specific to this particular plugin.

Now, let's explore this concept in a bit more detail by reading a section from the Capawesome blog.

How Capacitor Live Updates Work Under the Hood - Capawesome

This article provides a technical deep dive into how live updates function in Capacitor. We'll start with the foundational concept.

Please read the section titled Concept. It uses a diagram to visually separate the web and native layers and explains why the web layer can be replaced at runtime.

2. Apple App Store Policies

Apple's guidelines are notoriously nuanced. Failing to adhere to them can lead to app rejection or even removal. Understanding the rules for OTA updates is therefore critical.

The landing page for Apple's App Store Guidelines, where the rules governing OTA updates are defined.

At first glance, the policies can seem contradictory. It's essential to read two different documents together to get the full picture. The following article from the Bitrise Blog provides one of the clearest explanations available.

What App Stores allow with OTA updates: Apple and Google policy explained - Bitrise Blog

This article breaks down the legalistic language of the store policies into practical guidance for developers.

Read the section What does Apple's policy say about OTA updates?. Pay close attention to the distinction between App Store Review Guideline 2.5.2 and DPLA Section 3.3(b), and understand why the latter is the decisive rule for interpreted code like JavaScript.

As you've just read, the Developer Program License Agreement (DPLA) Section 3.3(b) is the key. It explicitly permits downloading "interpreted code" (which includes your React JS bundle) as long as it adheres to three crucial conditions:

  1. It must not change the primary purpose of the application. You can't submit a simple calculator app and then use an OTA update to turn it into a full-featured game or social network. The update should be consistent with the app's description and purpose as reviewed by Apple.
  2. It must not create a store or storefront for other code or applications. Your app cannot become a mechanism for distributing other apps or unvetted code, essentially creating an "app store within the App Store."
  3. It must not bypass signing, sandbox, or other security features of the OS. This is where the distinction between web and native code is vital. Your JavaScript runs within the secure sandbox of the WebView. It can only call native APIs through the Capacitor bridge, which was part of the reviewed native binary. You cannot use OTA updates to access private OS APIs or break out of the sandbox.

What can and cannot be updated on iOS?

Based on these rules, here is a practical summary of what is generally permissible to change via an OTA update on iOS:

Update TypeAllowed via OTA on iOS?Why?
Bug fixes (JS logic)YesDoes not change the app's purpose.
Performance improvements (JS)YesDoes not change the app's purpose.
UI/UX tweaks (CSS, layout)YesConsidered a minor change, not a change in core purpose.
Text, copy, and localizationYesContent update, not a functional change.
Adding a new featureGenerally NoThis is the gray area. If the feature is a minor addition that's consistent with the app's existing purpose, it might be okay. If it's a major new piece of functionality, it likely constitutes a change in "primary purpose" and requires a store review. The conservative approach is to submit new features through the App Store.
Changes to payment flowsNoAnything involving payments or subscriptions is highly scrutinized and must go through a formal review.
Native code changesNot PossibleOTA updates cannot alter the compiled native binary.

3. Google Play Store Policies

Google's policy on OTA updates is more straightforward and generally more permissive than Apple's. The rules are primarily located in the Device and Network Abuse policy.

Let's turn back to the Bitrise blog article for a concise explanation, and then we'll look at the specific clause in another resource.

What App Stores allow with OTA updates: Apple and Google policy explained - Bitrise Blog

This section of the article lays out Google's policy and its key exception.

Please read the section What does Google Play's policy say. Focus on the final sentence, which is the explicit carve-out that permits OTA updates for frameworks like Capacitor.

To reinforce this, the Capawesome blog quotes the exact same policy.

How Capacitor Live Updates Work Under the Hood - Capawesome

This section confirms the Google Play policy.

Read the short subsection titled Google Play Store. It highlights the key phrase regarding code running in an interpreter.

The key takeaway is Google's explicit exception:

"This restriction does not apply to code that runs in a virtual machine or an interpreter where either provides indirect access to Android APIs (such as JavaScript in a webview or browser)."

This sentence gives a clear green light for updating the web layer of a Capacitor app. Because your React code runs in a WebView (an interpreter) and accesses native APIs indirectly through the Capacitor bridge, it fits perfectly within this exception.

What can and cannot be updated on Android?

Google's rules are less concerned with the "primary purpose" of the app changing and more focused on the security model.

Update TypeAllowed via OTA on Android?Why?
Bug fixes (JS logic)YesPermitted by the interpreter exception.
Adding new JS-only featuresYesPermitted as long as the new feature complies with all other Google Play policies (e.g., content, privacy).
UI/UX tweaks and contentYesPermitted by the interpreter exception.
Native code changes (e.g., new plugins)Not PossibleOTA updates cannot alter the compiled native binary.
Changes to native permissionsNot PossiblePermissions are defined in the AndroidManifest.xml file, which is part of the native binary.

4. A Pre-Release Compliance Checklist

To distill this into an actionable process, you can use a simple checklist before every OTA release to ensure you're staying compliant.

What App Stores allow with OTA updates: Apple and Google policy explained - Bitrise Blog

The end of this article provides an excellent checklist for practical application.

Read the section titled What are the five things you should do before each OTA release?. This is a great summary to integrate into your release workflow.

Here is that checklist for your quick reference:

  1. Native Code Check: Has any native code changed? (e.g., did you add a new plugin?). If yes, you need a full store release.
  2. Functional Scope Check (iOS): Does this update significantly change what your app does or add a major new feature? If yes, default to a store release for Apple.
  3. Payment Check (Both): Does this update touch any part of a purchase, subscription, or entitlement flow? If yes, it requires a store review.
  4. Policy Compliance Check (Both): Does the new code comply with all other platform policies (e.g., content, user data, privacy)?
  5. Rollback Check: Is your mechanism for reverting to a previous version working? This is crucial for fixing a bad OTA push.

Conclusion

In this lesson, we have laid the critical groundwork for using OTA updates responsibly. You now understand the line between what can be updated instantly and what requires a full store review.

Here are the key takeaways:

  • Web Layer Only: OTA updates can only modify the web assets (JS, HTML, CSS) of your Capacitor app. Any changes to native code or plugins require a new app version submitted to the stores.
  • Apple's "Primary Purpose" Rule: Apple permits OTA updates for bug fixes and minor improvements but is strict about changes that alter the app's core purpose as it was originally reviewed.
  • Google's "Interpreter" Exception: Google's policy is more permissive, explicitly allowing updates to code running in a WebView, as long as it doesn't download executable native code and adheres to all other Play Store policies.
  • When in Doubt, Submit: If you are ever unsure whether an update complies with the rules, the safest course of action is always to submit it for a formal store review.

Now that we have a firm grasp of the policies, we can proceed to the exciting part. In our next lesson, we will get hands-on and install and configure a third-party OTA service into our Turborepo project.

Can't find a good explanation? Sign up and we'll make it for you

Sign up