A user receives an OTA update after a new publish under the following conditions:
- The Expo SDK version (major version, e.g., 33, 34) of the publish JS matches the SDK version of the app installed on their phone, and
- The release channel of the published JS matches the release channel of the app installed on their phone.
So, if you push an app to the store under SDK 34/ default release channel, and then later reference a native dependency (like AsyncStorage) in the code and publish updated JS to SDK 34/ default release channel, your app will break when users run the code referencing the native dependency.
To avoid the issue of breaking compatibility due to a change on the native side (in cases where I’m not updating the Expo SDK), I’ve incorporated a “minimum build number” into my release channels. So, my “prod-1001” release channel is used or any production JS that is compatible with binary builds numbered 1001 or later. Then, when I break compatibility, I update that to the new minimum build, so the old builds don’t get that new JS. More details here: How to check compatibility of OTA updates with custom native modules