Articles · App ExamplesUpdated September 2026

To auto-update an Android app, something in the build has to go looking for the update.

Nearly everyone who wants to auto-update an Android app wants the same thing: change the code, have it reach phones, skip the queue. Three different mechanisms get mixed together under that one phrase. Google Play installing your published version in the background is one. A prompt inside your app asking the user to take that version now is the second. Your app downloading a new JavaScript bundle at launch is the third. Only the third skips a release, it only covers part of the app, and it does nothing at all unless the installed build was made to do it. The release half of the story is in publishing to the App Store.

What follows separates the three, says what over the air app updates actually require, and what the store rules permit. It also gives the blunt answer for apps that were generated rather than hand built, where the usual truth is that nothing updates silently, because nothing in the binary is looking.

See where your change has to ship from

The short version

Google Play will update the app for you, it just will not skip the release.

Android app auto update is real and it is mostly free. Publish a version, and devices with automatic updates switched on install it in the background. What that never does is remove the build, the upload and the rollout that come first, which is the latency people are actually complaining about.

Over the air updates are the other thing, and they are narrower than the phrase suggests. They replace the JavaScript layer of an app that was built to fetch one. Native code, permissions and SDK versions still need a new binary, every single time.

What Google Play already does on its own

Start with the mechanism that is already installed on every phone. When you publish a new version, devices with automatic updates switched on fetch and install it in the background with no action from the user. For a lot of teams that is the whole of what they meant by auto update, and the real complaint is not about automation at all. It is that a build, an upload and a staged rollout all happen before Play has anything to hand out.

If you want a say in the timing, Google offers an in-app update API. Its documentation describes two flows. A flexible update downloads in the background while the person carries on using the app. An immediate update takes over the screen and requires the person to update and restart before continuing, which is what you reach for when the installed version is broken. Both need Android 5.0, API level 21, or higher, and both hand the actual install back to Google Play.

That last detail is the one that matters. Every option in this section still begins with a version you released. They change when and how the user is nudged. They do not change what has to happen before the nudge exists.

What an over the air update actually requires

Over the air updates work by putting a second copy of your JavaScript somewhere the app can reach, and having the app prefer it over the copy baked into the binary. Expo's EAS Update is the common service for React Native projects. It serves updates to projects using the expo-updates library, it covers the non-native pieces such as JavaScript, styling and images, and by default the client checks for an update every time the app is loaded, so users see the new version on their next launch.

The limits are structural, not a pricing tier. EAS Update cannot deliver native code changes, new native dependencies, changed app permissions or an Expo SDK upgrade, because all of those live in the binary. Runtime version policies exist to enforce exactly that: an update is only served to builds whose native side is compatible, and changing native code means a new runtime version and a new build.

So the requirement list is short and absolute. The update client has to be in the app before the app shipped. There has to be a runtime version to match against, and somewhere to publish bundles to. None of that can be added to a copy of the app that is already on someone's phone.

Which brings us to the honest part. Newly's Expo template does not include expo-updates. The generated project lists no such dependency, its app config has no updates block and no runtime version, and the standalone build pipeline explicitly turns the updates flag off so the app always launches the bundle embedded in it. A shipped build therefore fetches nothing at startup. When you change a screen, that change reaches users through a new build and a store release, not silently, and any claim otherwise is wrong.

Expo, EAS Update introduction

Try it

Where does this change ship from?

Pick what you changed, then say whether the installed app has an update client inside it.

New build, then a release

Nothing in the app is looking for an update, so the bundle inside the binary is the only one it will ever run.

What the store rules allow

There is a reason updating an app without a store release is narrow rather than merely difficult. Google Play policy forbids an app distributed through Play from modifying, replacing or updating itself by any method other than the Play update mechanism. Sideloading a new binary from your own server, or swapping out compiled code at runtime, is not a grey area.

The same policy carves out the space that JavaScript updates live in. The restriction does not apply to code that runs in a virtual machine or an interpreter that gives indirect access to Android APIs, such as JavaScript in a webview or browser. That is the opening every over the air update service works through, and it is also why the boundary sits exactly where it does: interpreted code yes, native binaries no.

Apple applies its own limits to downloaded code, and they are not identical, so a plan that works on Android is not automatically fine on iOS. If what you actually need is a fix in front of a handful of people this afternoon rather than everyone at once, the tester track is the faster road on both platforms, and on iOS that means ios testflight.

Google Play, Device and Network Abuse policy

Getting a change to real users today

If your app has no update client, the practical question stops being how to avoid a release and becomes how to make releases cheap enough that you stop minding. That is a solvable problem, and most of the pain in it is manual work that does not need to be manual.

On Android, the internal testing track carries a new build to a named list of testers without a public release, which is usually the right place for a fix you want someone to confirm before everyone gets it. Then promote the same build rather than rebuilding it. On the iOS side, the version bumps, the metadata and the upload can all be automated, which is what the app store connect api exists for.

Once releases are routine, the gap between writing a change and a user having it is measured in one build and one rollout. That is slower than an over the air push and considerably more predictable, because every user ends up on a binary you can name, rather than on a binary plus whichever bundle their last launch happened to fetch.

What each route actually gets you

RouteNeeds a new buildNeeds a public releaseWho gets it and whenCovers native changes
Play automatic updatesYesYesEveryone, after the rolloutYes
In-app update promptYesYesEveryone, on next openYes
Play internal testingYesNoYour tester list onlyYes
Over the air JS updateNoNoEveryone, on next launchNo
A build with no update clientYesYesEveryone, after the releaseYes

Adding over the air updates yourself

Bolting this on is not exotic, but it is not free either. You add the update client to the project, set a runtime version policy, point the app at a channel, and then you own a second distribution system: publishing bundles, watching which build each user is on, and rolling back a bad bundle quickly. Off-the-shelf builders tend not to include any of it, because it turns one artifact you can point at into two that have to stay compatible.

Newly is an AI app builder: you describe an app in plain English and it writes a real React Native and Expo project you own, running it on a cloud iPhone or Android simulator while it builds. It is $25 a month and there is no free plan. iOS goes out through TestFlight and App Store Connect with your own Apple Developer account. The Deploy tab has an Android section where one press builds, signs and uploads to Google Play internal testing, and it also produces a standalone release APK you can download and install on a phone directly. What it does not add is an update client, which is why the answer above is what it is.

The project is yours, so adding the update library later is an ordinary dependency change rather than a platform limitation. The part worth understanding before you start is the build that ships the change, because every route in this article eventually runs through it.

Questions people ask about auto-updating Android apps

Only partly. Google Play will install a published version automatically, but that still starts with a release you made. Skipping the release completely means an over the air update of the JavaScript layer, which works only if the installed build already contains an update client, and never covers native code, permissions or an SDK upgrade.

Ship the change, not a workaround

Describe what needs to change, get a build out to your tester list, and stop trying to route around a release that takes minutes.

Start building