Store Compliance

Over-the-air updates are allowed by both the App Store and Play Store — within limits. Code Push is built to stay inside those limits, but compliance also depends on what you ship and how. This page explains the rules, how Koolbase is designed around them, and how to use Code Push without putting your app at risk.

The one rule to remember

Code Push is for bug fixes and tuning, not for shipping major new features around store review. Updates must not be deceptive or change your app's primary purpose. Apps that use over-the-air updates to evade review can be removed from the stores.

Why this is allowed at all

Both Apple and Google generally prohibit downloading and running native executable code (Swift/Objective-C, Kotlin/Java) outside their review process. What they permit is interpreted code that runs inside a virtual machine with limited access to the OS.

That distinction is the whole basis of Flutter code push. Your Dart runs inside the Dart VM — not as native machine code with direct system access. Koolbase only ever touches that Dart layer. It never modifies native binaries, plugins, permissions, or the engine. Because the updated code stays inside the VM, it falls within the path the stores allow. This is the same basis the broader Flutter and React Native code-push ecosystem operates on.

Koolbase never ships native code

Both Runtime Bundles and VM Patches operate strictly above the native layer — config and assets in one case, Dart VM code in the other. Native code changes (Kotlin/Java, Swift/Objective-C), new permissions, and manifest changes always require a normal store release. Koolbase has no mechanism to deliver them, by design.

What code push can and can't change

A VM patch replaces your app's compiled Dart code — nothing else. Images, fonts, and other bundled assets live in the Flutter asset bundle, not the Dart snapshot, so a patch can't add or change them. If patched code references a bundled asset that isn't already in the shipped build, it won't load.

Patchable over the air:

  • UI layout, screens, widgets, navigation, and strings
  • Business logic, state, and theming — any Dart code
  • Dart dependencies, as long as they add no native code
  • Which remote image or font your code loads (see below)

Requires a normal store release:

  • Bundled assets — images, fonts, anything loaded via rootBundle / Image.asset
  • Native code (Kotlin/Java, Swift/Objective-C) and plugins that ship it
  • Permissions and manifest changes
  • The Flutter engine / SDK version

Working around the asset limit

You can change images and fonts without a store release by not bundling them: load them from a URL rather than the asset bundle, and let code push (or Remote Config) change which URL your app uses. Host the file in Koolbase Storage and reference its public cdn.koolbase.com URL — then a patch that swaps the URL, or a Remote Config change, updates the asset live. The asset travels over the network at runtime, so it never needs to be in the patch.

Google Play

Play's Device and Network Abuse policy prohibits self-updating outside the Play Store and downloading unauthorized executable code, but explicitly allows code that runs in a VM with limited API access — which is where Dart runs. The policy's real test is that dynamically delivered code must not enable a violation of Play policies.

Enforcement is intent-based: good-faith code that isn't doing anything malicious is treated as ordinary app code, not as a backdoor. In practice this means Android code push for bug fixes sits in well-established, accepted territory.

Apple App Store

Apple's guideline 2.5.2 is stricter. Apps may not download or execute code that changes features or functionality, with a narrow allowance for interpreted code that (a) does not change the app's primary purpose, (b) does not create a store for other code, and (c) does not bypass the OS's signing or sandbox protections.

The safe envelope on iOS is therefore narrower than on Android: ship bug fixes that keep your app doing the same thing it was reviewed to do. Don't use code push to introduce a materially new feature on iOS — that belongs in a store release. Apple does actively enforce 2.5.2.

iOS code push availability

iOS is fully supported, and compliant by construction: because Apple permits only interpreted — not compiled — downloaded code, Koolbase delivers iOS patches as signed bytecode executed by the engine's interpreter, never as downloaded machine code. See the Flutter Versions & Engines page for supported Flutter versions.

Android ABI coverage

Koolbase code-push currently ships engines for arm64-v8a and armeabi-v7a — together these cover effectively every physical Android phone in the field. x86_64 (used by emulators and a small number of devices) is not yet supported.

Because your plugins may bundle x86_64 native libraries, the AAB that koolbase release android produces can contain an x86_64 split with no Koolbase engine behind it — a device on that split would run without code-push. Before uploading to Play, restrict your build to the supported ABIs:

Groovy (android/app/build.gradle):

// android/app/build.gradle
            android {
              defaultConfig {
                ndk {
                  abiFilters 'arm64-v8a', 'armeabi-v7a'
                }
              }
            }

Kotlin DSL (android/app/build.gradle.kts):

// android/app/build.gradle.kts
            android {
              defaultConfig {
                ndk {
                  abiFilters += listOf("arm64-v8a", "armeabi-v7a")
                }
              }
            }

x86_64 support is on the way

Once a Koolbase engine ships for x86_64, this step goes away: the bundle will carry a code-push-capable x86_64 split and you can drop the abiFilters restriction. Until then, restricting ABIs ensures no device is ever served a split without code-push.

Staying compliant in practice

Do:

  • Use Code Push for bug fixes, crash fixes, and tuning config/flags
  • Keep releasing to the stores periodically — new users install from there, not from a patch
  • Keep updates honest: don't do anything a user wouldn't expect from your app's stated purpose
  • Ship larger feature work through a normal store release, then use patches to fix it

Don't:

  • Use Code Push to introduce a major new feature solely to skip store review
  • Change the app's primary purpose from what was reviewed and advertised
  • Ship anything deceptive, or that the store listing wouldn't lead a user to expect
  • Treat code push as a permanent replacement for store releases

Why keep shipping store releases

Code Push only updates an app after it's installed. New users always get the store build first, so that build should be current. Continuing to release periodically — to refresh screenshots, ship native changes, and keep your reviewed build in sync with reality — is both good practice and part of staying compliant. Think of Code Push as the fast lane between releases, not a replacement for them.

This is guidance, not legal advice

Store policies change and enforcement involves judgment. This page reflects the policies as Koolbase understands them and how the SDK is designed around them — it isn't legal advice. You are responsible for how you use Code Push in your app. If you have a high-stakes or unusual case, review the current App Store Review Guidelines and Play Device and Network Abuse policy, and consider professional advice.