Self-hosting leaves you to decide which device gets which bundle. Capawesome Cloud 178,914 , the hosted side of the same plugin (live updates from $9 a month, 14-day trial), decides on the server. You create an app in its console, put the generated appId into the plugin's config, and replace BookNest's update() with LiveUpdate.sync({ channel: 'production' }), which fetches the newest bundle this device may have and returns its nextBundleId (not run here: it needs a Cloud account). Or set autoUpdateStrategy: 'background' and the plugin syncs by itself at startup and on resume. Three ideas decide what sync() returns, and each is an option of @capawesome/cli apps:liveupdates:upload (version 4.21.0, whose --help lists them):
Channels (--channel) are named streams of bundles, such as production and beta. A device takes its channel from defaultChannel, setChannel() or the sync() call, so a hidden switch can move testers.
Rollouts (--rollout-percentage) release a bundle to part of a channel first. Capawesome notes that the percentage counts every device in the channel, including those the bundle's version range excludes.
Version ranges (--android-min, --ios-max and similar) tie a bundle to native version codes, so a bundle that needs a new plugin never reaches an old APK (Live Update Limits).
A release uploads to 10% and widens with apps:liveupdates:rollout --percentage 100 when crash reports stay quiet. Sign bundles too: apps:liveupdates:generatesigningkey makes a key pair, the upload signs with --private-key, and the plugin's publicKey option makes the app verify each bundle before using it, so a compromised server cannot push its own code.