HotupdaterHot Updater
Guides

Runtime Channel Switch

Temporarily move a device to another channel at runtime, then return to the default channel when needed.

Overview

Runtime channel switch lets a built app temporarily use a bundle from another channel without changing the default channel embedded in the binary.

  • The existing deployment process does not change.
  • HotUpdater.checkForUpdate({ channel }) checks another channel.
  • The switch is persisted only after updateInfo.updateBundle() succeeds.
  • You cannot jump directly from one switched runtime channel to another. Reset back to the default channel first.
  • HotUpdater.resetChannel() removes the switch and restores the original bundle.

Set your app's default channel first. See Default Channel Setup. Runtime channel switching is explicit. It only starts when you pass a specific channel to HotUpdater.checkForUpdate({ channel: "..." }). Calling HotUpdater.checkForUpdate() without channel keeps the existing update flow for the app's current channel.

Use this runtime channel switch flow when you want to opt a device into another channel without rebuilding the native app:

  1. Keep a build-time default channel such as production.
  2. Check another channel with HotUpdater.checkForUpdate({ channel: "beta" }).
  3. Call updateInfo.updateBundle() only when an update is returned.
  4. Reload the app to start using the installed bundle.
  5. Use HotUpdater.getChannel(), HotUpdater.getDefaultChannel(), and HotUpdater.isChannelSwitched() to show the current state in your UI.
  6. When you want to leave the runtime channel switch, call HotUpdater.resetChannel() and reload again.

This keeps the full lifecycle explicit:

  • Opt in with checkForUpdate({ channel }) + updateBundle() + reload()
  • Observe state with getChannel() + getDefaultChannel() + isChannelSwitched()
  • Opt out with resetChannel() + reload()

Opt Into Another Channel

import { HotUpdater } from "@hot-updater/react-native";

async function enableBetaChannel() {
  const updateInfo = await HotUpdater.checkForUpdate({
    updateStrategy: "appVersion",
    channel: "beta",
  });

  if (!updateInfo) {
    console.log("No beta bundle available");
    return false;
  }

  const installed = await updateInfo.updateBundle();

  if (!installed) {
    return false;
  }

  await HotUpdater.reload();
  return true;
}

Show Current State

import { HotUpdater } from "@hot-updater/react-native";
import { Text, View } from "react-native";

function ChannelStatus() {
  const currentChannel = HotUpdater.getChannel();
  const defaultChannel = HotUpdater.getDefaultChannel();
  const switched = HotUpdater.isChannelSwitched();

  return (
    <View>
      <Text>Current channel: {currentChannel}</Text>
      <Text>Default channel: {defaultChannel}</Text>
      <Text>Runtime switch active: {switched ? "yes" : "no"}</Text>
    </View>
  );
}

Reset to the Default Channel

import { HotUpdater } from "@hot-updater/react-native";

async function restoreDefaultChannel() {
  await HotUpdater.resetChannel();
  await HotUpdater.reload();
}

If the app is already switched to a runtime channel such as beta, do not try to jump directly to another runtime channel such as alpha. Call HotUpdater.resetChannel() and reload first, then start a new checkForUpdate({ channel: "..." }) flow from the default channel.

Important Behavior

  • The existing deployment process is unchanged.
  • checkForUpdate({ channel: "beta" }) only checks the beta channel.
  • HotUpdater.checkForUpdate() without a channel does not trigger runtime switching.
  • The app does not switch channels just by checking.
  • If no update is returned, the app stays on the current channel.
  • After updateInfo.updateBundle() succeeds and the app reloads, HotUpdater.getChannel() returns the effective runtime channel.
  • HotUpdater.getDefaultChannel() still returns the embedded default channel.
  • If a runtime channel switch is already active, checkForUpdate({ channel: "..." }) cannot move directly to a different runtime channel. Call HotUpdater.resetChannel() before starting another switch.
  • If no runtime channel switch is active, HotUpdater.resetChannel() is a no-op.

Do not rely on checkForUpdate({ channel: "<default-channel>" }) to return to the default channel. That call only checks for an update. If there is nothing new to install, the runtime channel switch remains active. Use HotUpdater.resetChannel() when you want to fully leave the runtime channel switch.