Releases & Patches
How VM Patches are organized: a release represents a binary you shipped, and patches are the ordered fixes you push on top of it. Understanding how devices are matched to a release is the key to pushing the right patch to the right users.
Releases
A release is a registered app binary — the build you shipped to a store (or sideloaded). It's the base that patches are applied against. When you push your first patch for a build, the CLI auto-creates the release if it doesn't exist — on iOS, patch push-ios derives the release's build_id from the binary you pass. Subsequent patches attach to the same release.
Each release belongs to a channel (e.g. stable or beta) and a platform. A device only ever receives patches from a release on its own channel.
Pushing a patch without the base binary
On Android, a patch is a diff against the base binary you shipped. When you register a release with koolbase release, the CLI now stores that base for you — so you don't have to extract libapp.so from your AAB by hand to push a patch later. (iOS patches aren't diffs, so this section applies to Android only.)
To push a patch against a stored base, pass --release <id> and omit --binary. The CLI fetches the stored base and diffs your new build against it:
# Patch a release whose base was stored at release time — no --binary
koolbase patch push --app <id> --release <release_id> --new fixed.so --diff \
--platform android --channel stable --publishYou still build your fixed code and pass it as --new — that's the update being shipped. Only the base is fetched for you.
Releases made before this still need --binary
patch push --release <id> without --binary will report that no base is stored. For those, either pass --binary <your base> as before, or ship a new release — from then on its patches need no --binary.Passing --binary always works
--binary is never required to be omitted. If you provide it, the CLI uses the binary you pass and skips the fetch — useful for any release, stored base or not.How a device matches a release
When the SDK checks in, it sends whatever identity it has for the running app. A release is registered to be matched one of two ways — its match mode:
- build_id — a content hash of the compiled snapshot's instruction section, stamped by
koolbase build. It identifies the exact compiled code: a change to only strings or assets keeps the same build_id; a logic change produces a new one. It survives Play App Signing and split-APK delivery intact, so it matches both sideloaded and Play Store builds. - release_version — the store versionName + versionCode (e.g.
1.4.0+503). Matches by the version you set rather than the exact binary, so you don't need to track the processed build's build_id. A convenient alternative for store workflows.
build_id wins when both are present
Choose the mode with --match-mode when pushing (defaults to build_id):
# Store app — match by version (survives Play re-signing)
koolbase patch push --app <id> --release <release_id> --new fixed.so --diff \
--match-mode release_version --app-version 1.4.0+503 \
--platform android --channel stable --publishPatches
A patch belongs to a release and carries a fix. Patches are auto-numbered per release — patch #1, #2, #3, in the order you push them. A device tracks which patch number it currently has applied.
The resolver always serves the highest published patch number for the matched release. If a device is on patch #2 and you publish #3, it picks up #3 on its next check. Patches are cumulative in intent — each new one represents the latest state of the fix, applied against the same base release.
Patch lifecycle
--publish to do both at once). A published patch can later be recalled, which reverts devices — see Rollout & Rollback.Channels
Channels let you ship to different audiences. The common setup mirrors Runtime Bundles:
| Channel | Use case |
|---|---|
stable | Production users. Push here once a patch is proven. |
beta | Internal testers or early adopters. Push here first. |
The device's channel is set in KoolbaseConfig.codePushChannel at init. A release and its patches live on one channel; the same build released to two channels is two separate releases with independent patch sequences.
Inspecting releases & patches
List the patches on a release from the CLI:
koolbase patch list --release <release_id>You can also view releases, patches, rollout state, and per-patch stats in the dashboard under your project's Code Push section.