Deploy
Deploy an update to one platform or both platforms sequentially.
Publish an update
Deploy builds and uploads the update files for each platform and publishes its
delivery policy. Each platform gets one ID, shared by the deployment output,
the console, and hotUpdater.getBundleId().
Checklist
- Complete manual setup or agent setup, including the server and client key.
- Connect the app with
HotUpdater.initand implement the custom update flow, then apply the native integration. - Install a release build with the intended channel and compatibility target.
For your first deployment, follow Test an OTA update to verify delivery in a test channel before using the commands below.
Options
Options:
-p, --platform <platform> specify the platform (choices: "ios", "android")
-t, --target-app-version <targetAppVersion> specify the target app version (semver format e.g. 1.0.0, 1.x.x)
-d, --disabled create the bundle disabled (default: false)
-f, --force-update force update the app (default: false)
-o, --bundle-output-path <bundleOutputPath> the directory where bundle archives will be generated
-r, --rollout <percentage> specify the rollout percentage for the new bundle (0-100) (default: 100)
-i, --interactive interactive mode (default: false)
-c, --channel <channel> specify the channel to deploy (default: "production")
-m, --message <message> Specify a custom message for this deployment. If not provided, the latest git commit message will be used as the deployment message
-h, --help display help for commandUsage
Deploy Both Platforms
Deploy each platform explicitly. To deploy iOS first and Android only after it succeeds, run:
npx hot-updater deploy -p ios -o .hot-updater/output/deploy/ios &&
npx hot-updater deploy -p android -o .hot-updater/output/deploy/androidEach command commits independently. If Android fails, the successful iOS update remains published. Keep the channel, rollout, and other delivery options consistent across both commands when they should share the same policy.
Omitting -p deploys both platforms in one command. It builds and uploads
each platform, then commits both in one database transaction, so neither is
published unless both succeed.
That command loads hot-updater.config.ts once for both platforms. A config
object gives them the same database and storage. A config that exports a
function runs it once for each platform, so create its adapters outside the
function and return the same ones. Otherwise deploy stops before it builds,
with Deploying multiple platforms requires a shared database configuration.
or Deploying multiple platforms requires a shared storage configuration.
// Created once, outside the function, so both platforms get the same adapters.
const storage = s3Storage({ /* ... */ });
const database = standaloneRepository({ /* ... */ });
// options is { platform, channel }, or null for a command without a platform.
export default defineConfig((options) => ({
build: bare({ enableHermes: true }),
storage,
database,
plugins: [insights(), apiKeys()],
// ... settings that depend on options?.platform or options?.channel
}));With -p, the archive is written directly to
<bundle-output-path>/bundle.tar.br. The commands above therefore produce
.hot-updater/output/deploy/ios/bundle.tar.br and
.hot-updater/output/deploy/android/bundle.tar.br. Without -p, each
platform's archive is written to <bundle-output-path>/<platform>/bundle.tar.br.
The manifest and unarchived files remain in the build adapter's output
directory, which is configured separately.
Deployment Result
After its database commit succeeds, each single-platform deploy prints its public Bundle ID:
Deployment successful
ID: 01a0586e-a286-7a74-a959-6d2c770b8793Record the ID from each platform's command.
Interactive deploy opens that exact update in the console. Use this ID with
bundle show, bundle update, bundle disable, bundle delete, or
bundle promote. The advanced patch command takes the Artifact ID shown in
Advanced diagnostics.
Bundle Diffing
New deployments upload a manifest and its per-file artifacts. The runtime reuses matching files from the current OTA or built-in app and downloads only the remaining files. No deploy flag is required for this behavior.
Hermes binary patch generation is enabled by default (patch.enabled: true).
Deploy therefore also tries to prepare compatible bsdiff patches. Set
patch.enabled: false only when you want to disable this optimization. Patch
generation is best-effort; a skipped patch does not fail the deployment because
the complete Hermes file remains available.
See Bundle Diffing for the runtime behavior and fallback rules.
Interactive Mode
Use interactive mode to choose deployment options with the keyboard:
npx hot-updater deploy -iThe -i (or --interactive) flag enables interactive keyboard input.
For Continuous Deployment (CD) Pipelines
Use -p to scope each CI job or step to exactly one platform:
npx hot-updater deploy -p iosUse -p android for Android, or the explicit sequence above
when one job deploys both platforms.
Force Update
Mark a Bundle as requiring immediate application when selected. A custom
update flow receives shouldForceUpdate: true and controls when to reload
after a successful download.
Run the following command:
npx hot-updater deploy -p <"ios" | "android"> -fThe -f (or --force-update) flag sets delivery behavior on the new Bundle. It
does not rewrite the uploaded artifact.
A forced Bundle stays required for devices that skip it. A device running an
older bundle that updates straight to a newer, non-forced Bundle still receives
shouldForceUpdate: true, as long as its cohort was eligible for the forced
one. Devices that already run the forced Bundle get later updates as deployed.
Channel
The -c (or --channel) flag specifies the release channel.
Run the following command:
npx hot-updater deploy -p <"ios" | "android"> -c "<channel>"The -c (or --channel) default is production.
For more details about default channels, refer to Default Channel Setup.
Rollout
The -r (or --rollout) flag sets the rollout percentage for the new Bundle.
Run the following command:
npx hot-updater deploy -p <"ios" | "android"> -r 25Use whole percentages from 1 to 99 for gradual rollout, 100 for a full
rollout, and 0 when you want to create the Bundle without exposing it to
numeric rollout until you edit the same Bundle later.
Hot Updater maps rollout percentages to 1..1000 numeric cohorts internally.
For example, -r 25 means 250 of 1000 numeric cohorts are eligible for that
Bundle. Numeric cohort selection is seeded by its ID and remains stable
when that Bundle's rollout policy changes.
If you omit -r, the default value is 100, so the new Bundle is eligible for
all numeric and valid custom cohorts immediately.
For more on gradual rollout, current device cohorts, and cohort targeting from the console, see Rollout & Cohorts.
Message
The -m (or --message) flag specifies the new Bundle's public message.
Run the following command:
npx hot-updater deploy -p <"ios" | "android"> -m "<message>"Pass the same -m value to each platform command when both updates should
share a message.
Force Update Flag Difference
| Update Type | Application in a custom flow | How to Enable |
|---|---|---|
| Default | Download, then reload at a safe point or apply on the next app start. | Default setting |
| Force Update | Read shouldForceUpdate: true and choose a reload point after download succeeds. | Use the --force-update flag or console. |
In the custom flow, shouldForceUpdate is a signal for your application to
call reload() after a successful download. Your code controls the restart;
setting the server flag alone does not restart the app.