---
modificationDate: August 06, 2026
title: Override update configuration at runtime
description: Learn how to override the update URL and request headers at runtime to control which update is loaded on the client side.
---

<AgentInstructions>

## Submitting Feedback

If you encounter errors, misleading or outdated information, report it so Expo can be improved:

Preferred command:
npx --yes submit-expo-feedback@latest --category docs --subject "/eas-update/override/" "<actionable feedback>"

Direct HTTP fallback:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/eas-update/override/","feedback":"🤖 Agent feedback for docs: <specific, actionable description> (<model>, <harness>)"}'

Only submit when you have something specific and actionable to report. Try to give the most context.

## Navigation

When answering a related or follow-up question, fetch the relevant page below as Markdown (.md) instead of guessing; use llms.txt for the full map.

You are here: EAS > EAS Update > Preview
Pages in this section:
- [Preview updates](https://docs.expo.dev/eas-update/preview.md)
- [Channel surfing](https://docs.expo.dev/eas-update/channel-surfing.md)
- [Override update configuration at runtime](https://docs.expo.dev/eas-update/override.md) (this page)
- [Using development builds](https://docs.expo.dev/eas-update/expo-dev-client.md)
- [GitHub PR previews](https://docs.expo.dev/eas-update/github-actions.md)
Full documentation tree: [llms.txt](https://docs.expo.dev/llms.txt)

</AgentInstructions>

This documentation is available as Markdown for AI agents and LLMs. See the [full Markdown index](/llms.txt) or append .md to any documentation URL.

# Override update configuration at runtime

Learn how to override the update URL and request headers at runtime to control which update is loaded on the client side.

The typical way to use EAS Update is to have a single update URL and a set of request headers (such as update channel name) embedded in a build of your app. To control which update is loaded you make changes on the server through the `eas update` command or the EAS dashboard. For example, you publish a new update to a channel that your build is pointing to, then the build fetches that update on the next launch. Updates published to a channel different from the one your build is pointing to will not be downloaded with this approach.

This guide explains how you can change the update URL and request headers at runtime, making it possible to load a specific update by ID or change the channel that updates are pulled from without creating and installing a new build.

## Override request headers

> The feature described in this section is available in Expo SDK 54 with the `expo-updates` version 0.29.0 and later.

For apps using EAS Update, the primary use case for this feature is [channel surfing](/eas-update/channel-surfing.md). Channel surfing switches the `expo-channel-name` request header at runtime as part of a complete channel switching workflow.

For example, if you have a `default` channel for production updates and a `preview` channel for preview updates, you can override the `expo-channel-name` request header to point to the `preview` channel. This enables you to test preview updates in your current production builds.

> Switching channels can cause compatibility issues when updates use different migrations or data shapes. See [Risks and considerations when switching channels](/eas-update/channel-surfing.md#risks-and-considerations-when-switching-channels).

Another potential use case is to provide different updates to different users, for example, so that a group of internal users (such as employees) receive updates before end-users.

### How it works

You can override request headers by calling [`Updates.setUpdateRequestHeadersOverride`](/versions/latest/sdk/updates.md#updatessetupdaterequestheadersoverriderequestheaders). With EAS Update, overriding the `expo-channel-name` request header makes the app request updates from the specified channel.

To override the `expo-channel-name` header at runtime, the native build must include it. When a build profile in **eas.json** defines `channel`, EAS Build sets this header automatically to that value. Builds created outside EAS Build (for example, with `npx expo run:android`) do not set it automatically. For those builds, declare the header in [`updates.requestHeaders`](/eas-update/getting-started.md#configure-update-channels-in-appjson) in your app config, then rebuild the app.

Provide a way for users to trigger the request header change in your app. This may be a hidden menu that only trusted users can access or another mechanism that fits your use case. After changing the request headers, call [`fetchUpdateAsync()`](/versions/latest/sdk/updates.md#updatesfetchupdateasync) to fetch the update and [`reloadAsync()`](/versions/latest/sdk/updates.md#updatesreloadasyncoptions) to reload the app. You can also wait for the next launch to fetch and install the update automatically.

```js
import * as Updates from 'expo-updates';

// Where you call this method depends on your use case - it may make sense to
// have a menu in your preview builds that allows testers to pick from available channels,
// for example:
Updates.setUpdateRequestHeadersOverride({ 'expo-channel-name': 'preview' });

// You can fetch and reload the update immediately, or wait for the next launch
await Updates.fetchUpdateAsync();
await Updates.reloadAsync();
```

#### Can I override other request headers?

Yes. Any other header you want to override at runtime must be declared in [`updates.requestHeaders`](/eas-update/getting-started.md#configure-update-channels-in-appjson) in your app config. The object you pass to `setUpdateRequestHeadersOverride()` replaces all custom request headers from the build, so include every header the app still needs while the override is active.

## Override both update URL and request headers

> The feature described in this section is available in Expo SDK 52 with the `expo-updates` version 0.27.0 and later. Using the `disableAntiBrickingMeasures` option is not recommended for production apps, it is currently primarily intended for preview environments.

Similar to [override request headers](/eas-update/override.md#override-request-headers), if you want to further override the update URL to a specific update, you can use the [`Updates.setUpdateURLAndRequestHeadersOverride`](/versions/latest/sdk/updates.md#updatessetupdateurlandrequestheadersoverrideconfigoverride) method. This allows you to load a specific update by ID, even if the update is published before the current build is created.

It is important to be familiar with the [security considerations](/eas-update/override.md#security-considerations) before deciding to use this feature in production. In the future, we may add support for a more restricted version of the feature that would be more suitable for this use case.

### How it works

There are two relevant APIs:

1.  `Updates.setUpdateURLAndRequestHeadersOverride({ updateUrl: string, requestHeaders: Object })` - this method overrides the update URL and the request headers that are specified in **app.json**/**Expo.plist**/**AndroidManifest.xml**, such as the `expo-channel-name` header.
2.  `disableAntiBrickingMeasures` - this field in the app config disables anti-bricking measures built-in to `expo-updates` which ensure subsequent updates can always be published to fix issues in previously-installed update. When you change this value, you will need to create a new build for it to take effect. **Do not enable this in your production builds.** The reason for this name is to clearly indicate that when you override the update URL/headers, we're no longer able to safely rollback to the previous update that was loaded. So, if the new update you have loaded causes the app to crash then `expo-updates`cannot automatically recover, because this field in conjunction with `setUpdateURLAndRequestHeadersOverride` will disable embedded updates and therefore there will not be any update to rollback to. The user would need to uninstall and reinstall the app. You should only use this feature in preview builds.

How to use these APIs:

1.  **Override the update URL/headers, instruct user to close the app**: Somewhere in your app, you would provide a way for users to trigger the change to the URL and/or request headers. This may be in a hidden menu that only trusted users have access to, or some other mechanism depending on your use case. When the parameters are changed, notify the user that they need to close and re-open the app, such as via an alert. The `expo-updates` library, with methods like `checkForUpdateAsync()`, will not use the new overridden URL and request headers until the app is closed and reopened.
2.  **The new update will be downloaded and launched on the next app open**: After the app is completely closed ("killed" and not just backgrounded) and re-opened, the update and its related assets will all be downloaded. Once they are ready, the app will launch. While it's downloading, the user will have to wait on the splash screen. We understand that waiting on the splash screen is not ideal, and we intend to improve this experience in the future if this feature is widely used. For the currently recommended use case (previews), this is likely an acceptable compromise.

### Security considerations

The anti-bricking measures that can be disabled with `disableAntiBrickingMeasures` ensure that, no matter what update is published, you can always publish another update afterwards that will be applied. By disabling the anti-bricking measures, certain categories of attacks and exploits become possible, especially around in-house (compromised employee) publishing of malicious updates. For example, an employee with the ability to publish updates could publish a malicious update that changes the update URL and request headers to point to their own server, and take over installations of the app. This risk can be mitigated, but not eliminated, by using [code signing](/eas-update/code-signing.md) for production updates and limiting access to the key.

#### Did similar usage of CodePush carry the same risk?

Yes. CodePush allowed developers to swap deployment keys with `sync({ deploymentKey: string })` which could be used maliciously take over an app installation in this same way.

### Example code

Here's an example of how you might use these APIs:

```js
import * as Updates from 'expo-updates';

// Where you call this method depends on your use case - it may make sense to
// have a menu in your preview builds that allows testers to pick from available
// pull requests, for example.
function overrideUpdateURLAndHeaders() {
  Updates.setUpdateURLAndRequestHeadersOverride({
    updateUrl: 'https://u.expo.dev/{updateId}/group/{groupId}',
    requestHeaders: {},
  });

  alert('Close and re-open the app to load the latest version.');
}
```

```json
{
  "expo": {
    "updates": {
      // We recommend only enabling this in preview builds.
      // You can use app.config.js to configure it dynamically.
      "disableAntiBrickingMeasures": true
      // etc..
    }
  }
}
```
