Deploy updates

Edit this page

Learn a simple but powerful process for safely deploying updates to your users.


When you have an app with multiple binary versions in production (this is common — users do not always stay up to date with your latest store release), it's important to understand what code is running on which versions and to be able to specifically target a particular version with a hotfix.

EAS Update provides "channels", "branches", and "runtime versions" to help you determine which app version to target, to help you with bookkeeping to understand the state of your deployments, and to support a variety of deployment patterns.

What if my preferred release process isn't supported by EAS Update?

Release management is a large topic in software engineering, and everyone has a slightly different take on how they would like to do it. EAS Update is designed to support a variety of different workflows, but this guide will focus on the simplest workflow that works for most apps. That said, there are some other workflows that may not work within the constraints of the EAS Update service. For example, each binary version must always point to a single channel, and you cannot dynamically update the channel.

As an escape hatch, you can host your own update service that is compatible with the Expo Updates Protocol and point your expo-updates configuration to that service instead. The only concepts relevant to update selection that exist on the protocol level are "Runtime Version" and "Platform", and you are free to create your own concepts on top of those in the same way we built channels and branches. Learn more about creating a custom expo-updates server.

A simple release process

In this guide, we'll describe a simple but powerful release process that uses channels and runtime versions, and mostly ignores branches. This gives most of the benefits of EAS Update with a minimal amount of conceptual overhead. You can evolve this process to suit your needs as they arise, or move to other deployment patterns.

Why ignore branches in this release process?

The most simple way to use EAS Update is to ignore the concept of "branches" and focus on "channels". Branches will still exist, but you will not have to interact with them directly to manage deployments. You can keep your channels pointed at a branch with the same name as the channel and think of them as a singular concept.

EAS Update branches were meant to map to Git branches and enable teams to publish changes from a Git branch directly to an EAS Update branch of the same name. This can be helpful for previewing updates, but for many apps, this level of integration with Git is not required. Often, developers are only interested in being able to release hotfixes to a staging or production version of their app manually, and can run eas update --channel staging or eas update --channel production, when needed rather than managing branches to accomplish the same result.

Configuring your project

Channels will indicate which environment the update targets (such as "production" or "staging"), and runtime versions will indicate the app version that the update will target (such as "1.0.0" or "1.0.1").

Channel configuration

Run eas update:configure in your project if you haven't already.

If you use EAS Build, the default configuration that will be applied by the configure command, which is almost what we want to use here: each profile will point to a channel of the same name, so our production release of our app will point to the "production" channel. We only need to add a "staging" profile that points to the "staging" channel.

Example eas.json configuration

The following configuration is approximately what eas update:configure will generate for you if you haven't already configured your project.

{
  "build": {
    "production": {
      "channel": "production"
    },
    "staging": {
      "channel": "staging"
    },
    "preview": {
      "channel": "preview",
      "distribution": "internal"
    }
  }
}

If you do not use EAS Build, you will need to modify the channel used in your native project configuration. When you release to production, ensure you update the channel name in native config to "production", and when you release to staging, ensure you update the channel name in native config to "preview". It's worth noting that using EAS Build with EAS Update helps you get the best out of the product, but it is not required.

Runtime version configuration

By default, eas update:configure will set "runtimeVersion": { "policy": "appVersion" } in your app config. This is the recommended configuration, it will ensure that the runtime version of your app is always the same as the app version, and you have a unique runtime version to target for every release of your app. In this case, the app version refers to the native version of your app that users will see on the app store, and it does not include the build number or version code. For example: "1.0.0" will be used as the runtime version, and not "1.0.0(1)" (where 1 is the build number or version code).

Example app.json configuration
{
  "expo": {
    "runtimeVersion": {
      "policy": "appVersion"
    }
  }
}
What about the fingerprint runtime version policy?

We hope that this will be the future of runtime version policies, but for now, we recommend using the "appVersion" policy. The "fingerprint" policy is experimental and not yet widely recommended.

Deploying previews

You can preview updates in your internal distribution release builds or in development builds. Using internal distribution instead of deploying to a store beta track reduces the friction of distributing the app to internal testers, and is suitable for cases where you want to, for example, share a build on every pull request or an early concept that you're working on.

Internal distribution release builds

As explained above, preview builds will point to the "preview" channel. If you want multiple versions of the preview app distributed internally at any given time, you can change the channel name based on the feature name. For example, you might set your channel on your build to "preview-feature-a" when working on feature A, and then set it to "preview-feature-b" when working on feature B.

Preview in development builds

Development builds can load updates from any channel, provided the runtime version is compatible. Learn more about this in Previewing updates.

Deploying to staging

Run eas update --channel staging to publish an update to staging. This will make your hotfix immediately available to users of staging builds with the targeted runtime version.

Your staging environment will be Google Play Beta or TestFlight — the "beta track" on respective app stores. You may alternatively use internal distribution, but deploying to a store beta track is generally recommended when you are staging code for a production release since users are able to access it without any knowledge of internal processes for distributing the app (while using internal distribution would require users to download the app from an expo.dev URL).

A common practice for creating staging builds is to always create one whenever you upload a production build to a store. This allows you to have a staging build with an identical runtime to the production build, which you can use to test your updates before rolling them out to production. With EAS Build, this means running eas build --profile staging --auto-submit every time you run eas build --profile production --auto-submit.

Deploying to production

Run eas update --channel production to bundle and push a new update to production. This will make your hotfix immediately available to production build users with the same runtime version.

If you have already published the fix to staging and verified it there, ensure that you are republishing from the same commit.

For this release process we recommend using identical environment variables and code signing configuration on staging as on production, to ensure that updates verified in staging work exactly the same in production. If do this, then you can eas update:republish --destination-channel production to promote the update rather than generating a new one. This will ensure the exact same bundle that you tested in staging is used in production.

Run eas update --channel production to publish an update to production. This will make your hotfix immediately available to users of production builds with the same runtime version.

Runtime versions

When creating a new production build, we recommend incrementing your app version to ensure it has a unique runtime version for each release of your app.

Gradually rolling out updates

Rollouts that leverage multiple branches can't be used with this workflow. We're working on a solution for this, but in the meantime, you will need to use a process similar to the branch promotion flow to incrementally roll out updates.

Learn more in Rollouts.

Rolling back to a previous update version

If you've mistakenly published an update to any of your environments, you can run eas update:rollback initiate a rollback to a previous update.

Learn more in Rollbacks.

Next steps

  • Learn more about the Persistent staging release process, which is very similar to what is described here.
  • Explore using preview updates in development builds.