Skip to main content
Tutorial

Does Apple Allow Live Updates Without App Store Review?

Yes, within limits. Apple allows over-the-air updates of interpreted code like JavaScript, as long as the app keeps its purpose. Here is the exact rule and how it applies to Capacitor apps.

Does Apple Allow Live Updates Without App Store Review? Capgo blog illustration

Short answer: yes, Apple allows live updates, within limits. You can push new JavaScript, HTML and CSS to an iOS app without a new App Store review, as long as the update does not change what the app is. You cannot download native code.

With Capgo: Capgo live updates ship only the web layer (JavaScript, HTML, CSS, assets) of a Capacitor app, which Apple’s rules allow when the update keeps the app’s primary purpose, does not create a code storefront, and does not bypass OS security; native changes still go through a store release.

Most of the confusion comes from mixing two different things: live updates of interpreted code (allowed) and downloading new executable code (not allowed). This page quotes the rules, shows where the line is, and explains how Apple enforces it.

This is not legal advice. It is how the rules read today and how thousands of apps use them in production.

What Apple’s rules actually say

Two texts matter. The first is App Store Review Guideline 2.5.2:

Apps should be self-contained in their bundles, and may not read or write data outside the designated container area, nor may they download, install, or execute code which introduces or changes features or functionality of the app, including other apps.

Read alone, that sounds like a ban. The exception lives in the second text, section 3.3.1(B) of the Apple Developer Program License Agreement, which every developer signs:

Interpreted code may be downloaded to an Application but only so long as such code: (a) does not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store, (b) does not create a store or storefront for other code or applications, and (c) does not bypass signing, sandbox, or other security features of the OS.

So the rule is not “no downloaded code”. It is “no downloaded native code, and interpreted code only under three conditions”.

A Capacitor app’s web layer is JavaScript, HTML and CSS running in WKWebView, which is Apple’s own WebKit engine. That is interpreted code, so it falls under the exception. Guideline 4.7 points the same way: Apple explicitly lets apps run HTML5 and JavaScript content that is not embedded in the binary.

Where the line is

Allowed with a live update Not allowed with a live update
Bug fixes in your JavaScript, HTML, CSS Downloading Swift, Objective-C or any compiled binary
UI changes, copy changes, new screens in your existing web stack Changing the app into a different product (a notes app becoming a casino)
A/B tests and gradual rollouts of web code Unlocking features hidden from App Review
Updating images, translations, config Building a store that installs other apps or code
Rolling back a bad release Bypassing the iOS sandbox, signing or permissions

Capgo only ships the left column. It replaces the web bundle inside your app. Anything native, such as a new Capacitor plugin, a new permission, or an SDK upgrade, still needs a regular App Store release. Capgo’s version targeting makes sure a bundle that needs new native code never reaches an old binary.

How Apple enforces it

Apple judges substance, not technology. Nobody gets pulled for fixing a typo over the air. The pattern Apple goes after is an app that passes review as one thing and becomes another thing afterwards. That is guideline 2.3.1 (no hidden or undocumented features) as much as 2.5.2.

In practice:

  • Ship what you would have submitted, just faster.
  • Keep every update within the purpose described in your App Store listing.
  • Send big feature launches through App Review, and use live updates for fixes and iteration between releases.
  • Never use a live update to switch on behavior that reviewers did not see.

If you follow that, live updates are a normal part of shipping an iOS app. React Native teams have done it for years with CodePush and Expo Updates, and Capacitor teams do it with Capgo.

Which stacks can do it on iOS?

Whether your app can ship over-the-air updates on iOS depends on one question: is your app logic interpreted at runtime? JavaScript and other interpreted code, yes. Swift, Objective-C and C++ compiled to machine code, no. AOT-compiled frameworks such as Flutter qualify only through an interpreter.

iOS live update compatibility by stack

Stack How the code runs on iOS Live updates allowed? Tooling
Capacitor JavaScript, HTML, CSS in WKWebView (WebKit) Yes Capgo
Ionic (on Capacitor) Same as Capacitor Yes Capgo
Cordova JavaScript in WKWebView Yes Capgo after migrating to Capacitor, legacy Cordova plugins
React Native / Expo JavaScript bundle on Hermes or JavaScriptCore Yes, JavaScript only Expo Updates, self-hosted CodePush alternatives
NativeScript JavaScript on an embedded engine Yes, JavaScript only Limited, mostly self-built
Flutter Dart compiled AOT to machine code Only through an interpreter Shorebird (Dart interpreter for patches)
Native Swift / Objective-C Machine code No for native code; yes for JavaScript in WebKit or JavaScriptCore Remote config and server-driven UI
.NET MAUI / Xamarin C# compiled AOT to machine code No Remote config only
Kotlin / Compose Multiplatform Kotlin/Native compiled to machine code No Remote config only
Unity / Unreal C# via IL2CPP or C++, compiled No for code, yes for content Asset bundles, scripted content (Lua)
Web wrapper (remote URL) Website loaded in a WebView Always live, but review risk None needed, see note below

Capacitor, Ionic and Cordova: fully covered

Your app’s web UI and JavaScript business logic run in WKWebView, while the native shell and plugins remain native. Apple’s Developer Program License Agreement section 3.3.1(B) permits downloaded interpreted code only when it preserves the app’s primary purpose, does not create a code storefront, and does not bypass OS security. Guideline 4.7 separately governs apps offering HTML5 and JavaScript mini apps and adds additional requirements.

A live update replaces the web bundle. The native shell, plugins and permissions stay the ones Apple reviewed. That is why Capgo is compliant by design: it cannot change native code even if you wanted it to. New native plugins or permissions still need an App Store release.

React Native and Expo: JavaScript yes, native modules no

React Native runs your JavaScript bundle on Hermes or JavaScriptCore. That bundle is interpreted code and can be updated over the air, which is what Expo Updates and Microsoft CodePush (retired in 2025) were built for. Teams leaving CodePush need a replacement.

Any change to native modules, the React Native version, or Info.plist needs a new binary.

Flutter: only through an interpreter

On iOS, Flutter compiles Dart ahead of time to ARM machine code. Downloading new machine code is forbidden, so stock Flutter cannot use live updates. Shorebird solves this by running patched Dart code in an interpreter, which brings it under the interpreted code exception. Read more in live updates for Flutter apps.

Native Swift, .NET MAUI, Kotlin Multiplatform: no native code updates

These stacks produce native machine code. They cannot download replacement native code. A native app may still download and execute interpreted code, such as JavaScript through JavaScriptCore, when it meets Apple’s conditions. What you can also do over the air is change data: remote config, feature flags for features already reviewed, server-driven UI, images and copy.

Unity and game engines: content yes, code no

Game code is compiled. Asset bundles (levels, art, balancing data) are content and can be downloaded. Embedded scripting languages like Lua are interpreted code and follow the same rules as JavaScript.

Remote URL wrappers: live, but risky for review

An app that only loads your website in a WebView is “updated” every time you deploy the site. The problem is not guideline 2.5.2 but guideline 4.2 (minimum functionality): Apple rejects apps that are just a website in a frame. Bundling the web app with Capacitor, adding native features, and using live updates avoids that.

What no stack can do on iOS

Whatever your framework, a live update cannot:

  • Download native code, frameworks or dynamic libraries
  • Add new permissions or entitlements
  • Change the app into something the App Store listing does not describe
  • Turn on features that were hidden from App Review

Where to go next

Ship fixes today, not after review

Capgo live updates push JavaScript, HTML and CSS changes to your Capacitor app in minutes, with channels, rollbacks, delta updates and end-to-end encryption. It is open source and can be self-hosted.

bunx @capgo/cli@latest init

Follow the quickstart to send your first update.

Live updates for Capacitor apps

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

Latest from our Blog

Capgo gives you the best insights you need to create a truly professional mobile app.