App version management

Edit this page

Learn about different version types and how to manage them remotely or locally.


Android and iOS each expose two values to identify the version of an app: the version visible in stores (user-facing version) and the version visible only to developers (developer-facing build version). This guide explains how you can manage those versions remotely or locally.

Automatic App Version Management
Automatic App Version Management

In this Expo feature focus video you'll learn about automatic app version management in Expo EAS Build.

App versions

In Expo projects, the following properties can be used to define app versions in the app config file.

PropertyDescription
version The user-facing version visible in stores. On Android, it represents versionName name in android/app/build.gradle. On iOS, it represents CFBundleShortVersionString in Info.plist.
android.versionCodeThe developer-facing build version for Android. It represents versionCode in android/app/build.gradle.
ios.buildNumberThe developer-facing build version for iOS. It represents CFBundleVersion in Info.plist.

Using app versions in your app

To show the user-facing version inside your app, you can use Application.nativeApplicationVersion from the expo-application library.

To show the developer-facing build version inside your app, you can use Application.nativeBuildVersion from the expo-application library.

Recommended workflow

User-facing version

When you are doing a production release, the user-facing version should be explicitly set and updated by you. You can update the version property in app config when production build is submitted to the app stores. This also applies if your project uses 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.

Developer-facing build version

For developer-facing build version, you can set them to autoincrement on every build. This will help you avoid making manual changes to the project every time you upload a new archive on Play Store testing channels or TestFlight. One common cause for app store rejections is submitting a build with a duplicate version number. It happens when a developer forgets to increment the developer-facing build version number before creating a new build.

EAS Build can help manage developer-facing build versions automatically by incrementing these versions for you if you opt into using the remote version source, which is the recommended behaviour. Optionally, you can choose to use a local app version source, which means you control versions manually in their respective config files.

Remote version source

The remote version source is the recommended behavior from EAS CLI version 12.0.0. If you are using an older version of the EAS CLI, local is the default.

EAS servers can store and manage your app's developer-facing build version (android.versionCode and ios.buildNumber) remotely. To enable it, you need to set cli.appVersionSource to remote in eas.json. Then, under the production build profile, you can set the autoIncrement property to true.

eas.json
{
  "cli": {
    "appVersionSource": "remote"
  },
  "build": {
    "development": {
      %%placeholder-start%%... %%placeholder-end%%
    },
    "preview": {
      %%placeholder-start%%... %%placeholder-end%%
    },
    "production": {
      "autoIncrement": true
    }
  }
  %%placeholder-start%%... %%placeholder-end%%
}

The remote version is initialized with the value from the local project. For example, if you have android.versionCode set to 1 in app config, when you create a new build using the remote version source, it will auto increment to 2. However, if you do not have build versions set in your app config, the remote version will initialize with 1 when the first build is created.

When the remote version property is enabled inside eas.json, the build version values stored in app config are ignored and not updated when the version is incremented remotely. The remote version source values are set on the native project when running a build, which is considered the source of truth for these values. You can safely remove these values from your app config.

Syncing already defined versions to remote

There are different scenarios where you already have versions set up for your project and want to increment from those versions when you create a new EAS Build. However, these existing versions might not be synced remotely with EAS. Some of these scenarios are:

  • You have already published your app in the app stores and want to continue using the same version numbers.
  • EAS CLI is not able to detect what version the app is on.
  • For any other reason, you have versions explicitly set, such as inside your app config.

In these scenarios, you can sync the current version to EAS Build using the EAS CLI using the following steps:

  • In the terminal window, run the following command:

    Terminal
    eas build:version:set
  • Select the platform (Android or iOS) when prompted.

  • When prompted Do you want to set app version source to remote now?, select yes. This will set the cli.appVersionSource to remote in eas.json.

  • When prompted What version would you like to initialize it with?, enter the last version number that you have set in the app stores.

After these steps, the app versions will be synced to EAS Build remotely. You can now set build.production.autoIncrement to true in eas.json. When you create a new production build, the versionCode and buildNumber will be automatically incremented.

Syncing versions from remote to local

To build your project locally in Android Studio or Xcode using the same version stored remotely on EAS, update your local project with the remote versions using the following command:

Terminal
eas build:version:sync

Limitations

  • eas build:version:sync command on Android does not support bare projects with multiple flavors. However, the rest of the remote versioning functionality should work with all projects.
  • autoIncrement does not support the version option.
  • 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.

Local version source

The remote version source as a recommended behavior has been introduced in eas-cli version 12.0.0. If you are using an older version of the CLI, you don't need to specify the version source explicitly to local.

You can configure your project so that the source of truth for project versions is the local project source code itself. To do this, set cli.appVersionSource to local in your eas.json.

With this setup, EAS reads app version values and builds projects as they are. It doesn't write to the project. You can also enable auto incrementing versions locally by setting the autoIncrement option on a build profile.

eas.json
{
  "cli": {
    "appVersionSource": "local"
  },
  "build": {
    "development": {
      %%placeholder-start%%... %%placeholder-end%%
    },
    "preview": {
      %%placeholder-start%%... %%placeholder-end%%
    },
    "production": {
      "autoIncrement": true
    }
  }
  %%placeholder-start%%... %%placeholder-end%%
}

In the case of existing React Native projects, the values in native code take precedence. The libraries expo-constants and expo-updates read values from the app config file. 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 config.

Limitations

  • 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.
  • autoIncrement is not supported if you are using a dynamic config file (such as app.config.js).
  • For existing 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.