Rolling back a release
Rollback returns a deployment to an earlier release:
aether rollback MyApp ProductionWithout a target it goes back to the release before the current one. To land on a specific version:
aether rollback MyApp Production --targetRelease v4Rollback creates a release, it deletes nothing
Section titled “Rollback creates a release, it deletes nothing”The server copies the target release into a brand-new release at the head of the history, with a new label, releaseMethod: Rollback, and originalLabel pointing at the release it restored. History stays complete: you can see the bad release, the rollback, and everything before them.
Because it is a normal new release, devices pick it up through the standard update flow. The new release starts enabled and with no rollout limit, so every device that checks in gets it.
Guards
Section titled “Guards”The server answers 409 with a code field in three cases. Branch on the code; the wording of error is not part of the contract. The CLI prints the message and not the code, so at a terminal match on what the command printed.
rollback_target_current: the target is already the deployment’s latest release.rollback_version_mismatch: the target’s binary version differs from the current release’s, so the request is refused; upload a new release for the current binary instead. Rolling back from a disabled concrete release to an older covering range is the same refusal; the exits for that case are under Automatic halt.release_halted: the target is disabled and the automatic halt put it there, so restoring it would ship its bundle again at 100%. Today the CLI prints, in part,it is disabled, and the release auto-halt halted it for failed installs.
See Errors and rate limits for how error responses are shaped.
The halt guard applies to whichever release you land on, whether you named it or the server picked the one before the current release. Say you are rolling back from v5, and v4, the release the server would pick on its own, is halted. You have two ways past it. Roll back to a healthy release instead:
aether rollback MyApp Production --targetRelease v3Or override the halt by re-enabling the halted target first, naming its label:
aether patch MyApp Production -l v4 --disabled falseThe -l matters. Without it aether patch targets the deployment’s latest release, which in this situation is the release you are trying to get away from.
A release disabled by hand and never halted rolls back as usual.
Automatic halt
Section titled “Automatic halt”Aether can also disable a failing release on its own, without creating anything.
Every few minutes it works through the deployments, checking each one’s latest enabled release. Every release has an evaluation window, which opens when the release starts serving and opens again each time you re-enable it. Aether disables the release only when three thresholds are met within its current window: enough distinct devices were served the release, enough distinct devices reported a failure, and the failure rate among the served devices reached the configured limit. Repeated reports from one device count once per window, and the minimums are deliberately high, so a release seen by only a handful of devices cannot be halted whatever its rate.
Halting is not rolling back. Aether switches the release off:
- It stops being offered. Devices on a binary that no release targeted exactly are served the newest enabled release that still covers them, which is usually the one they are already running. Devices on a binary whose own release was the one just disabled are not moved to an older wider range that still covers that binary. They are not offered another OTA until you re-enable the release, upload a new release for that exact binary, or upload a newer covering range. Devices that already confirmed an earlier package keep running it; fresh installs of that binary stay on the store binary until one of those exits. Rolling the deployment back to the older range answers
409withrollback_version_mismatch; use one of those three exits instead. - Devices that installed it and crashed before confirming it have already rolled back on their own.
- Nothing is deleted, no release is created, and the history is unchanged. The API does treat a halted release differently from one you switched off yourself: see below.
Aether emails the account that owns the tenant, falling back to the billing address. The email names the app, deployment and label, and the distinct-device counts behind the decision. The usual next step is to ship a fix for that binary. If the previous release was a wider range covering the same binary, do not roll back to it: the server answers 409 with rollback_version_mismatch. Use the three exits above. If you judge the halt wrong, re-enable the release, naming the label the email gave you:
aether patch MyApp Production -l v5 --disabled falseRe-enabling a release starts a fresh evaluation window. Device counts from the previous window do not count against it, but new failures can make Aether disable the same release again. The early warning described under staged rollouts is sent once per release rather than once per window, so a release that was already warned gets its second halt without another warning. Once the release reaches its configured lifetime limit, which defaults to two automatic halts, another manual re-enable stays in place and Aether will not disable that release again. A release you ship afterwards has its own history and evaluation windows.
Each window counts distinct devices, not raw reports. A failed install contributes only when its status report identifies the release label, so older SDK reports that carry only a binary version are not part of the decision.
A halt is more than a disable
Section titled “A halt is more than a disable”Devices cannot tell a halted release from one you switched off yourself, but the API can. While the halt stands, the server refuses three requests that would treat the release as healthy. Each answers 409 with code set to release_halted:
- A rollback that lands on it, the
release_haltedguard above. - A promotion of it to another deployment as an enabled release.
- A raise of its rollout percentage, while that rollout is unfinished.
Promotion has a way through that leaves the halt standing. aether promote copies the source release’s disabled flag unless you override it, so promoting a halted release lands a disabled copy in the destination and is not refused; only an explicit --disabled false on the promote is. The copy is still a new release. When it targets a range of binary versions, it switches off every enabled release in the destination whose range overlaps that range, and devices on those versions have nothing to install until you enable the copy. When it targets one concrete binary version and lands disabled, destination releases for that same version stay enabled.
The rollout raise has no such path. While the halt stands a raise on its own is refused, and re-enabling the release in the same aether patch overrides the halt and applies the raise together:
aether patch MyApp Production -l v4 --disabled false -r 75That puts a release Aether disabled for failed installs back in front of devices, at the new percentage. Run it only once you have decided the halt was wrong. Raising the rollout of a release whose rollout has already completed is a different refusal, with code set to resource_already_exists.
Re-enable the release and the three refusals stop: rollback, promotion and rollout raises all work again.
Client-side rollback is different
Section titled “Client-side rollback is different”The SDK also rolls back on its own when an update crashes before it confirms itself. That mechanism is per-device: it changes what one phone runs and nothing else. Both operations on this page act on a whole deployment instead, whether you run the rollback yourself or Aether disables the release for you. The update lifecycle page covers the client side.