How Does the Zigbee OTA (Over-the-Air) Firmware Update Process Work?
Last updated 12 July 2026 · 8 min read
Direct Answer
Zigbee delivers firmware updates through a dedicated ZCL cluster — the OTA Upgrade cluster (0x0019) — rather than any mechanism built into the network or MAC layer. An OTA server (the coordinator, a gateway application, or a bridge like Zigbee2MQTT) advertises a new image with an Image Notify command; each client device then asks whether an update actually applies to it with a Query Next Image Request, matching the response against its own manufacturer code, image type, and current file version; if a newer compatible image exists, the device pulls it down piece by piece with a sequence of Image Block Request/Response exchanges sized to fit within a single Zigbee frame; and once the full image is received and verified, the device signals readiness with an Upgrade End Request and the server tells it when to apply the update. The cluster only governs how the image bytes get from the network to the device's application — the device's own bootloader and flash-partition mechanics, covered separately, are what actually make the update power-loss-safe once the bytes arrive.
Detailed Explanation
Zigbee has no OTA mechanism at the network or MAC layer — updating a device's firmware is an application-layer concern, handled entirely by the OTA Upgrade cluster (cluster ID 0x0019) defined in the Zigbee Cluster Library. Any device that supports field firmware updates implements this cluster as a client; the coordinator, a gateway application, or a bridge such as Zigbee2MQTT implements the server side. The cluster's job is narrow and specific: get a new firmware image from the server to the client's application, reliably, over a network built for small and infrequent payloads rather than bulk transfer. What the device does with those bytes afterward — staging, verifying, and activating the update — is a separate concern, covered in how does an OTA firmware update work?. See the Zigbee topic for the full set of Zigbee implementation guides.
Image Notify: Announcing an Update Is Available
The server initiates the process with an Image Notify command, sent unicast to a specific device, or broadcast/groupcast to many devices at once. Image Notify carries a "payload type" field that controls how much information the server includes up front — from a bare notification with no detail, up to the full manufacturer code, image type, and new file version — and a jitter parameter that spreads out the responses from a broadcast notification so that dozens or hundreds of devices don't all immediately hammer the server with queries at once.
Image Notify is advisory, not mandatory: a client is not required to act on it immediately, and many implementations also poll for updates periodically on their own schedule rather than relying solely on being notified.
Query Next Image: Does This Update Apply to Me?
Whether prompted by an Image Notify or acting on its own schedule, the client sends a Query Next Image Request containing its manufacturer code, image type, current firmware version, and (optionally) its hardware version. The server compares this against the images it has available and replies with a Query Next Image Response — either "no image available" or the file version, size, and identifying fields of a matching newer image.
This matching step is what prevents a device from ever being offered firmware built for a different product or hardware revision: manufacturer code and image type must match exactly, and file version must be genuinely newer than what the device already reports running.
Image Block Transfer: Moving the Bytes
Once a client has confirmed an update exists, it requests the image in a sequence of Image Block Request/Response exchanges. Each request asks for a specific offset and a block size the client can currently accept — sized to fit comfortably within a single Zigbee frame, typically on the order of tens of bytes per block given ZCL and network-layer overhead, meaning a multi-hundred-kilobyte application image can require many thousands of individual block exchanges to complete. The client requests the next block only after successfully processing the previous one, giving natural flow control without needing a separate acknowledgement scheme.
An optional Image Page Request variant lets a server proactively stream a run of consecutive blocks without waiting for a request between each one, reducing round-trip overhead on networks where that's worthwhile — support for this is implementation-dependent on both ends.
Upgrade End: Confirming and Activating
After the client has received every block and validated the image (at minimum a CRC over the completed download, per the OTA file format described below), it sends an Upgrade End Request reporting success or a specific failure reason. The server responds with an Upgrade End Response that can either instruct the device to apply the update immediately or specify a delay — letting an operator coordinate a rollout so that, for example, a large batch of devices doesn't all reboot into the new firmware at the same instant.
The Zigbee OTA File Format
Images distributed through this cluster use a standardised file header (distinct from any MCU-specific bootloader image format such as MCUboot's) containing: a file identifier "magic number," a header version, the manufacturer code, image type, file version, a stack version field (Zigbee vs Zigbee Pro), a header string field for a human-readable description, and the total image size. This header is what the Query Next Image matching in the earlier step actually compares against — it exists specifically to let a mixed-vendor network safely host many different products' update images without any device risking installation of an incompatible one.
Where This Fits Against MCU-Level OTA
It's easy to conflate the Zigbee OTA Upgrade cluster with the dual-partition, verify-and-swap bootloader mechanics covered in how does an OTA firmware update work? — they solve different halves of the same problem. The ZCL cluster is purely a transport: it gets image bytes from a network-connected server onto the device's application, block by block, over a link designed for small sensor payloads rather than firmware-sized transfers. What the device's application does with those bytes — writing them to a secondary flash slot, verifying a hash or signature, and only then instructing the bootloader to switch active images on next boot — is exactly the A/B partition and confirmation model described on that page, and applies here regardless of Zigbee being the delivery mechanism rather than Wi-Fi or BLE.
Practical Examples
A self-hosted smart-home deployment using Zigbee2MQTT hosts vendor-published OTA images locally (or fetches them from each vendor's public index) and serves them to paired devices through its own OTA Upgrade cluster server implementation — the end user triggers an update from the Zigbee2MQTT frontend, and the underlying Image Notify/Query Next Image/Block Request sequence runs automatically against the selected device.
A commercial lighting product line staggers a firmware rollout across a large installed base by broadcasting Image Notify with jitter to avoid every fixture in a building starting its block-transfer sequence simultaneously, and sets an Upgrade End Response delay so fixtures don't all reboot (briefly dropping light output) at the same moment during business hours.
Design Considerations
- Battery-powered end devices need a longer update window than routers. Because a sleepy end device can only receive image blocks while briefly awake at its poll interval, plan field rollouts assuming end devices take substantially longer to complete a transfer than mains-powered routers, and avoid campaigns with an aggressive completion deadline that assumes router-speed transfer for every device.
- Manufacturer code and image type must be assigned and managed deliberately. A product line with multiple hardware revisions or SKUs needs its image type and manufacturer code scheme planned before the first OTA-capable unit ships, since this is the only mechanism preventing an incompatible image from ever being offered to the wrong hardware variant.
- Stagger broadcast rollouts rather than notifying an entire mesh at once. Image Notify's jitter parameter and a deliberately staged Upgrade End Response delay both exist to prevent a large deployment from saturating the mesh with simultaneous block-transfer traffic or rebooting an entire installation's worth of devices at the same instant.
- The OTA cluster's CRC is not a substitute for image signing. Add cryptographic signature verification inside the image itself, checked by the device's bootloader after the ZCL transfer completes, for any product where an unauthenticated firmware image would be a meaningful security risk.
- Zeus Design's firmware team designs OTA update architecture for connected products, including the application-layer distribution logic and the underlying bootloader/partition design it depends on.
Common Mistakes
- Assuming Image Notify guarantees the update happened. Image Notify is advisory — a client can ignore it, and confirming an update actually completed requires tracking the Upgrade End Request/Response exchange, not just that a notification was sent.
- Treating the ZCL OTA transfer as the whole safety story. A device whose application-level bootloader doesn't implement proper A/B partitioning and verified activation can still be bricked by a corrupted or truncated transfer, even though the OTA Upgrade cluster itself behaved correctly — see the Common Mistakes in how does an OTA firmware update work? for the underlying bootloader failure modes this can expose.
- Broadcasting Image Notify to an entire mesh without jitter or staggered activation, causing many devices to start block transfers or reboot simultaneously and degrading mesh performance for the duration of the rollout.
- Forgetting to plan router density for the rollout period specifically, not just normal operation — a mesh that's marginal on Router coverage under everyday traffic can degrade further under the sustained additional load of a firmware rollout; see what is Zigbee?'s Design Considerations for why Router density, not device count, drives mesh reliability.
- Not versioning images with a scheme the Query Next Image comparison actually respects, leading to a device repeatedly being offered — or never being offered — an update because its file version field doesn't sort the way the rollout logic assumes.
Frequently Asked Questions
- Can a Zigbee OTA update brick a device?
- Yes, if the device's own bootloader and flash-partition design doesn't protect against it — the ZCL OTA cluster itself is only a transport mechanism for getting image bytes onto the device, not a guarantee of a safe activation. A device implementation that overwrites its only firmware copy in place, rather than staging the new image in a secondary flash area and verifying it before switching over, can be left unbootable by a truncated transfer, a corrupted block, or a power loss during the final write. See how does an OTA firmware update work? for the dual-partition, verify-before-swap design that makes the underlying update safe regardless of which network delivered the image.
- Do battery-powered Zigbee end devices receive OTA updates the same way as mains-powered routers?
- The cluster commands are identical, but the practical experience is not. A router is reachable at any time, so its Image Block Request/Response exchange proceeds as fast as the network allows. A sleepy end device only checks in with its parent at its configured poll interval, and image blocks can only be delivered when the device is briefly awake — so a multi-hundred-kilobyte image can take substantially longer to fully transfer to a battery-powered end device than to a router, and some device implementations temporarily shorten their poll interval during an active OTA transfer specifically to avoid an update that never finishes.
- Does the OTA Upgrade cluster verify that an image is safe to install, or just that it downloaded correctly?
- The cluster's own built-in check is a CRC over the downloaded image data, confirming only that the transfer completed without corruption — it says nothing about whether the image is authentic or was actually produced by the legitimate manufacturer. The Zigbee OTA file format's header includes a manufacturer code and image type that the client checks before accepting an update, which prevents accidentally installing an incompatible product's firmware, but this is not cryptographic authentication. Manufacturers concerned with supply-chain or malicious-update risk add their own signature verification inside the image itself, checked by the device's bootloader after the ZCL transfer completes — the same signing and verification layer described in how does an OTA firmware update work?, applied on top of whatever transport (Zigbee, Wi-Fi, BLE) actually delivered the bytes.
References
Related Questions
What Is Zigbee?
Zigbee is an IEEE 802.15.4 mesh protocol for smart home and building automation. Covers coordinator/router/end device roles, ZCL, range, and module selection.
How Do You Set Up a Zigbee Coordinator with Zigbee2MQTT?
How to set up a Zigbee coordinator with Zigbee2MQTT: dongle selection, flashing, pairing devices, network map visualisation, and the MQTT bridge.
How Do You Choose a Zigbee Module or SoC for a Product Design?
Zigbee SoC and module selection for product design: CC2652R vs EFR32MG21 vs BL702 compared by multiprotocol support, SDK maturity, and cost.
How Does an OTA Firmware Update Work?
OTA firmware updates require dual-bank flash, image verification, and rollback. Covers MCUboot swap, ESP32 OTA API, image signing, and power-loss-safe design.
How Do You Decode a Cortex-M HardFault Using the CFSR, HFSR, and MMFAR/BFAR Registers?
A Cortex-M HardFault leaves diagnostic data in the CFSR, HFSR, MMFAR, and BFAR registers plus a stacked register frame. Here's how to read them.
How Do STM32 RDP and WRP Option Bytes Protect Flash Memory?
STM32 RDP levels (0/1/2) and WRP sector protection guard flash — but RDP Level 2 permanently disables debug access. Here is how to use them safely.
Related Forum Discussions
Battery Zigbee sensor keeps 'disappearing' from Zigbee2MQTT and won't come back without a manual re-pair — is this a routing issue?
Running a Zigbee2MQTT network with a Sonoff ZBDongle-E coordinator and about 15 devices — mostly mains-powered smart plugs acting as routers
Global variable initialized to non-zero value but always reads as zero in main() — bare-metal STM32
Bit of a basic question maybe, but I'm genuinely stuck. Moving from ESP32/Arduino to bare-metal STM32 (STM32G031, Makefile project, arm-none