Skip to content

Pausing deployments

When a rollout looks wrong, the question is not "how do we undo firmware that's already on devices?" That ship has sailed. The question is "how do we stop offering it to anyone new, and how do we get a known-good build to the affected devices?".

SimpleOTA gives you two layers of defence: an automatic on-device safety net (SimpleOTAClient v0.2.0+, Arduino) and server-side levers you can pull for the whole fleet.

0. On-device automatic rollback (Arduino, v0.2.0+)

SimpleOTAClient v0.2.0 introduces trial-install rollback: after apply() the library marks the new image as a trial and reverts to the previous partition if confirmRunning() is not called within the timeout. The rolled_back event is then reported to the server, which auto-pauses the deployment (default: on, threshold 1) so no further devices are offered the bad update.

For the full lifecycle, the timer-arming caveats, and the managed-mode auto-confirm behaviour, see the dedicated Trial install and rollback guide.

This is your first line of defence: a bad build is caught on the first device that receives it. The manual Pause button in section 1 below covers the cases where auto-pause does not apply: deployments with the auto-pause toggle off, failure modes that do not surface as a rolled_back event, or devices using firmware without trial-install support.

1. Pause

Go to the deployment and click Pause. From that moment:

  • New /check/ requests behave as if the deployment didn't exist.
  • Devices already mid-download are not interrupted (the URL is short-lived but already issued).
  • Cohort decisions are preserved; resuming later picks up exactly where you left off, same buckets, same seed.

Pause is always safe and always reversible. Use it as the first reflex when something looks off.

2. Roll forward with a fix

Pausing stops the bleed; it does not heal devices that already flashed the bad build. Those devices are now reporting their new current_build_number and need a higher build number to update again.

The fix path:

  1. Build a corrected firmware. Bump nothing manually: the upload itself allocates a higher build number than anything previously uploaded in the project.
  2. Upload it.
  3. Create a deployment targeting the same audience as the broken one, at a high percentage (often 100 immediately, since the canary has already happened, badly).
  4. Pause or supersede the broken deployment.

3. Reverting via republish

If the latest build is broken and the previous one was fine, you can republish the previous binary as a new artifact (yes, with a new, higher build number; there's no rewinding). Upload it again, deploy it. The bytes on the device end up identical to the previous good release.

This is intentional: the integer comparison artifact.build_number > device.current_build_number is the only comparison the engine does. Republishing is how you tell the fleet "actually, go back to that".

4. What about devices that won't update?

If the bad build has bricked the OTA path itself (device can't reach /check/ anymore), you're past what FOTA can fix.

For Arduino (SimpleOTAClient v0.2.0+): the trial-install timeout described in section 0 above covers the most common bricking scenario. If the bad firmware ships without trial support, physical re-flash is the only remaining option.

For ESP-IDF: esp_https_ota integrates with the bootloader's rollback mechanism by default. We strongly recommend calling esp_ota_mark_app_valid_cancel_rollback() only after a successful health check (network up, sensors ok, serial heartbeat); never blindly on boot.