Over-the-air firmware updates are no longer a luxury feature for IoT products — they are a fundamental requirement. Any device shipped without a robust, secure OTA pipeline is a device that cannot be fixed in the field, cannot receive security patches, and cannot evolve with customer needs. In this guide, we walk through the architecture, code, and security measures required to implement production-grade OTA updates on the ESP32 family of microcontrollers.
Why ESP32 OTA Updates Matter for IoT Devices
The economics of IoT are unforgiving. A device recall costs orders of magnitude more than the device itself — shipping, logistics, customer disruption, and reputational damage compound quickly. OTA enables three critical capabilities:
- Security patches — vulnerabilities in TLS stacks, Wi-Fi drivers, or application logic can be remediated within days instead of months. For a broader view of IoT vulnerabilities, read our common IoT security mistakes guide.
- Feature rollouts — deploy new functionality to a deployed fleet without hardware revision spins.
- Bug fixes — edge cases discovered in production can be patched immediately.
The ESP32, with its dual-core architecture, hardware cryptographic accelerators, and generous flash memory options, is one of the best-supported platforms for secure OTA. The ESP-IDF framework provides a comprehensive OTA subsystem that, when configured correctly, gives you a production-ready update pipeline out of the box.
ESP32 Dual Partition OTA Architecture
The foundation of safe OTA on ESP32 is the dual-partition (A/B) scheme. The flash is divided into two equal-sized application partitions — conventionally named ota_0 (factory) and ota_1 — plus an otadata partition that tracks which slot is active and whether the last update was successful.
The bootloader reads otadata to decide which partition to boot. After an OTA write completes, the bootloader attempts to boot the new image. If the new application fails to validate itself (via the esp_ota_mark_app_valid_cancel_rollback() call), the bootloader falls back to the previous known-good partition on the next reset.
Why A/B? Single-slot OTA (write-in-place) risks bricking a device if power is lost mid-write or if the new firmware is corrupt. A/B partitioning guarantees that one valid firmware image always exists, making the update atomic from the system's perspective.
Partition Table Setup
For an ESP32 with at least 4 MB of flash, a typical partition table for A/B OTA looks like this:
# ESP32 Partition Table — 4 MB Flash, A/B OTA
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
ota_0, app, ota_0, 0x10000, 0x1C0000,
ota_1, app, ota_1, 0x1D0000, 0x1C0000,
The otadata partition (8 KB) stores the current boot state. Each application partition gets roughly 1.75 MB, which is sufficient for most ESP32 applications including the WiFi stack, TLS, MQTT, and application logic. If your firmware exceeds this, consider moving to an 8 MB or 16 MB flash part and adjusting partition sizes accordingly.
Secure OTA Firmware Update: ESP32 Code Flow
The ESP-IDF OTA API follows a straightforward sequence. Here is the canonical flow used in production builds:
esp_ota_begin(next_partition, OTA_SIZE_UNKNOWN, &out_handle);
esp_ota_write(out_handle, binary_data, data_len);
esp_ota_end(out_handle);
esp_ota_set_boot_partition(next_partition);
esp_restart();
Step by step:
esp_ota_begin()— initialises the OTA write context and targets the inactive partition. PassingOTA_SIZE_UNKNOWNallows variable-length updates; you can also pass the exact binary size for stricter validation.esp_ota_write()— writes firmware chunks as they arrive over the network. Chunked writing enables streaming updates without buffering the entire binary in RAM.esp_ota_end()— finalises the write and verifies the integrity of the written image against its checksum.esp_ota_set_boot_partition()— sets the otadata to point at the newly written partition on next boot.esp_restart()— triggers a hardware reset. On boot, the bootloader reads otadata and boots the new image.
Production tip: Always validate the downloaded binary's signature before calling esp_ota_begin(). This prevents writing a tampered or corrupted image to flash, reducing wear and enabling early rejection of invalid updates.
Secure OTA Firmware Update: HTTPS, Certificate Pinning & Signed Binaries
Security for OTA operates at three layers:
Transport Layer — HTTPS with TLS
The firmware binary should always be served over HTTPS. The ESP32's esp_http_client supports TLS out of the box. Configure it with esp_tls_cfg_t to verify the server certificate against the CA certificate bundled in firmware. Never disable certificate verification in production. For a comparison of encryption algorithms used in OTA transport security, see our AES-256-GCM vs ChaCha20-Poly1305 guide.
Identity Layer — Certificate Pinning
Even with HTTPS, a compromised CA could issue a valid certificate for your update server. Certificate pinning (public key pinning) embeds the expected server certificate's public key or SHA-256 hash in the firmware. The TLS handshake then checks that the server presents the pinned key, providing an additional layer of defence against CA compromise.
// Certificate pinning in esp_tls_cfg_t
esp_tls_cfg_t tls_cfg = {
.cacert_buf = (const unsigned char *)server_cert_pem,
.cacert_bytes = server_cert_pem_len,
.crt_bundle_attach = NULL,
.skip_common_name = false,
};
Binary Layer — Firmware Signing
The most critical security mechanism is cryptographic signing of the firmware binary itself. Using esp_secure_boot, the bootloader verifies an ECDSA signature on the application image before executing it. This means even if an attacker compromises the update server or the TLS connection, they cannot flash a malicious binary.
Enable signing in menuconfig under Security Features → Enable hardware Secure Boot. The build process generates a signing key that signs each firmware binary; the corresponding public key is burned into eFuses on the chip. Once burned, it cannot be changed — making the hardware root of trust immutable.
Secure Boot and Flash Encryption
Secure Boot and Flash Encryption are complementary features that together provide a robust security posture:
- Secure Boot — the ROM bootloader verifies the application bootloader's signature; the application bootloader verifies the partition table and each application binary's signature. This creates a verified chain of trust from the moment the chip powers on.
- Flash Encryption — encrypts the contents of external flash using an AES-256-GCM key stored in eFuses. This protects against physical attacks: an attacker cannot read the firmware by desoldering the flash chip. Combined with Secure Boot, it prevents both reading and modifying the firmware.
Both features require burning eFuses, which is irreversible. Enable them early in the product lifecycle — retrofitting Flash Encryption to a deployed fleet is extremely difficult and requires a firmware update path that itself must be secure by design.
Rollback Strategy
The ESP-IDF rollback mechanism makes A/B updates safe. When the bootloader boots a new partition, it marks the update as "pending verification." The new application must explicitly call esp_ota_mark_app_valid_cancel_rollback() to confirm that it is functioning correctly. If the application crashes, resets, or fails to call this function within the configured timeout, the bootloader reverts to the previous partition on the next boot.
Enable this in menuconfig:
Component config → ESP-ASCOM-specific CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE → Enable
Call the confirmation function after your application has initialised all critical subsystems — networking, sensors, and application logic — and determined that the system is healthy:
esp_err_t ret = esp_ota_mark_app_valid_cancel_rollback();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Rollback confirmation failed: %s", esp_err_to_name(ret));
}
If the call fails, the bootloader will revert on next reset — a safe default that prevents bricking.
ESP32 OTA Updates: Triggering Models for IoT
How your device knows an update is available depends on your deployment architecture. The three most common models are:
- HTTPS pull-based — the device polls a version endpoint (e.g.,
GET /api/v1/firmware/version?current=1.2.3) on a schedule. Simple, stateless, and easy to secure. The server returns a redirect or download URL if a newer version exists. Best for devices with periodic connectivity. - MQTT-triggered — the device subscribes to a firmware notification topic. The backend publishes an OTA trigger message containing the download URL and expected hash. This model enables near-instant updates with minimal polling overhead. Requires MQTT with TLS and authentication.
- Hybrid — use MQTT for urgent security patches (immediate notification) and HTTPS polling for routine updates (nightly check). This gives you the best of both worlds: low-latency for critical fixes and simple periodic maintenance for non-critical updates.
Staggered Rollout Strategy
Pushing a firmware update to your entire fleet simultaneously is risky. Even with thorough QA testing, production environments reveal edge cases that staging does not. A staggered rollout mitigates this:
- Canary group (1–5% of devices) — internal or beta testers receive the update first. Monitor crash rates, connectivity, and application-level metrics for 24–48 hours.
- Gradual roll (20–50%) — expand to a broader cohort. Continue monitoring key health indicators.
- Full deployment — after the canary and gradual phases pass without issues, roll out to 100%.
On the server side, this requires a device registry that tracks firmware versions and allows target groups. On the device side, the rollback mechanism ensures that any device that fails can revert autonomously, but the staggered approach reduces the blast radius of a bad update before it reaches most of the fleet.
Common Pitfalls and How to Avoid Them
Over years of building OTA pipelines, these are the most frequent issues we encounter:
- Insufficient flash space — the application binary exceeds the partition size. Monitor binary size in CI; add a CI gate that fails the build if it exceeds 90% of the partition capacity.
- Missing or corrupt otadata — if the otadata partition contains invalid data, the bootloader may fail to boot. Use the factory provisioner to write a valid initial otadata. Include a fallback that erases and resets otadata if the bootloader detects corruption.
- Power loss during OTA write — the dual-partition scheme handles this by design, but ensure your hardware has sufficient bulk capacitance to complete a write in progress. For battery-powered devices, require a minimum battery level before initiating an OTA.
- Rollback confirmation never called — the application crashes before reaching the confirmation call, and the device perpetually reboots. Implement a "boot count" counter and force a stable factory reset after N failed boot attempts.
- Certificate expiry — the server TLS certificate expires while devices are in the field. Set up certificate monitoring and renewal automation. Use long-lived CA-signed certificates with automated renewal, or implement a certificate update mechanism via the OTA pipeline itself.
- Large OTA binary size — large binaries take longer to download, increasing the window of vulnerability to network interruptions. Compress the binary with gzip or zlib and decompress on the device. ESP-IDF supports compressed OTA natively.
Conclusion
Secure OTA is not a checkbox feature — it is an architectural commitment. Every device you ship without a reliable update mechanism is a liability that compounds with every vulnerability disclosure, every bug report, and every feature request from your customers.
The ESP32 provides an excellent foundation: hardware Secure Boot, Flash Encryption, a mature OTA subsystem, and a vibrant ecosystem. When you combine dual-partition updates with signed binaries, TLS certificate pinning, a robust rollback strategy, and a staggered rollout pipeline, you build a system that can grow with your product through its entire lifecycle.
If you are designing an IoT product today, invest in OTA infrastructure from day one. Retrofitting it later is technically possible but operationally painful — and the gap between shipping and fixing is measured in customer trust.
Need help designing your OTA pipeline? Aletheia Tech specialises in embedded firmware security, from partition planning to full deployment pipelines. Get in touch for a consultation.