1--- 2title: App version management 3--- 4 5import { Collapsible } from '~/ui/components/Collapsible'; 6 7Android and iOS each expose two values that identify the version of an application; one that is visible in stores, and another that is visible only to developers. 8 9In managed projects, we use fields `version`/`android.versionCode`/`ios.buildNumber` in **app.json** to define versions, where `android.versionCode`/`ios.buildNumber` represents the developer-facing build version and `version` is the user-facing value visible in stores. For bare projects, each of those values maps to specific parts of the native configuration: 10 11- [`version`][config-version] field in **app.json** on iOS represents `CFBundleShortVersionString` in **Info.plist**. 12- [`version`][config-version] field in **app.json** on Android represents `versionName` in **android/app/build.gradle**. 13- [`ios.buildNumber`][config-ios-buildnumber] field in **app.json** represents `CFBundleVersion` in **Info.plist**. 14- [`android.versionCode`][config-android-versioncode] field in **app.json** represents `versionCode` in **android/app/build.gradle**. 15 16One of the most frequent causes of app store rejections is submitting a build with a duplicate version number. This happens when a developer forgets to increment the version number prior to running a build. 17 18EAS Build can manage automatically incrementing these versions for you if you opt in to using the "remote" app version source. The default behavior is to use a "local" app version source, which means you control versions manually in their respective config files. 19 20To simplify the descriptions, we will use **app.json** terminology (`version`/`versionCode`/`buildNumber`) for the rest of this page, but unless stated otherwise, the same applies to bare projects. 21 22## Examples 23 24<Collapsible summary="Remote version source"> 25 26With this **eas.json**, the version for all builds will be based on the value stored on EAS servers, and the version will be incremented remotely and only when building with `production` profile. 27 28```json 29{ 30 "cli": { 31 "appVersionSource": "remote" 32 }, 33 "build": { 34 "staging": { 35 "distribution": "internal", 36 "android": { 37 "buildType": "apk" 38 } 39 }, 40 "production": { 41 "autoIncrement": true 42 } 43 } 44} 45``` 46 47</Collapsible> 48 49<Collapsible summary="Local version source"> 50 51With this **eas.json**, the version for all builds will be based on the value from **app.json** or native code. When you build using `production` profile, the version will be incremented in the local code before the build. 52 53```json 54{ 55 "cli": { 56 "appVersionSource": "local" 57 }, 58 "build": { 59 "staging": { 60 "distribution": "internal", 61 "android": { 62 "buildType": "apk" 63 } 64 }, 65 "production": { 66 "autoIncrement": true 67 } 68 } 69} 70``` 71 72</Collapsible> 73 74## Remote version source 75 76You can configure your project to rely on EAS servers to store and manage the version of your app. Add `{ "cli": { "appVersionSource": "remote" } }` in your **eas.json**. The remote version will be initialized with the value from the local project. If you would like to explicitly set the value directly, or EAS CLI is not able to detect what version the app is on, you can use the `eas build:version:set` command. EAS stores version information scoped by account, slug, platform, and application ID/bundle identifier — so, for example, if you are building variants with different application IDs or bundle identifiers, versioning will be independent for each of them. 77 78If you want to build your project locally in Android Studio or Xcode using the same version stored remotely on EAS, you can update your local project with the remote versions using `eas build:version:sync`. 79 80Enabling the `autoIncrement` option in the remote app version source mode is currently only available for `versionCode`/`buildNumber`. 81 82When using a remote app version source, the values in **app.json** will not be updated when the version is incremented remotely, and so the local and remote values will fall out of sync. The remote source values will be set on the native project when running a build, and they are the source of truth — however, the values specified in your **app.json** will be present in `Constants.expoConfig` and `Constants.manifest` exposed by `expo-constants`. Use `expo-application` to determine your application version at runtime instead, and remove `versionCode`/`buildNumber` from your **app.json**. 83 84### Limitations 85 86- `eas build:version:sync` command on Android does not support bare projects with multiple flavors, but the rest of the remote versioning functionality should work with all projects. 87- `autoIncrement` does not support the `version` option. 88- It's not supported if you are using EAS Update and runtime policy set to `"runtimeVersion": { "policy": "nativeVersion" }`. For similar behavior, use the `"appVersion"` policy instead. 89 90### Recommended workflow 91 92The main goal of this feature is to avoid manual changes to the project every time you are uploading a new archive to run it on TestFlight/Play Store testing channels. When you are doing a production release, the user-facing version change should be explicit. 93 94We recommend updating `version` field after a new build goes live in the store, especially if you are using `expo-updates` with an automatic runtime version policy. This marks the beginning of a new development cycle for a new version of your app. [Learn more about deployment patterns](/eas-update/deployment-patterns.mdx). 95 96## Local version source 97 98By default, the source of truth for project versions is the local project source code itself. In this case, EAS does not write to the project, it reads the values and builds projects as they are. 99 100You may opt in to auto incrementing versions locally with the `autoIncrement` option on a build profile, but it comes with some limitations. 101 102In the case of bare React Native projects, values in native code take precedence, and `expo-constants` and `expo-updates` read values from **app.json**. If you rely on version values from a manifest, you should keep them in sync with native code. Keeping these values in sync is especially important if you are using EAS Update with the runtime policy set to `"runtimeVersion": { "policy": "nativeVersion" }`, because mismatched versions may result in the delivery of updates to the wrong version of an application. We recommend using `expo-application` to read the version instead of depending on values from **app.json**. 103 104### Limitations 105 106- With `autoIncrement`, you need to commit your changes on every build if you want the version change to persist. This can be difficult to coordinate when building on CI. 107- `autoIncrement` is not supported if you are using a dynamic config (**app.config.js**). 108- For bare React Native projects with Gradle configuration that supports multiple flavors, EAS CLI is not able to read or modify the version, so `autoIncrement` option is not supported and versions will not be listed in the build details page on [expo.dev](https://expo.dev). 109 110[config-version]: /versions/latest/config/app/#version 111[config-android-versioncode]: /versions/latest/config/app/#versioncode 112[config-ios-buildnumber]: /versions/latest/config/app/#buildnumber 113