Part 7by Muhammad

OTA Update Strategies: Delta vs Full Firmware (What to Use When)

OTA update strategies Delta vs Full firmware

OTA update strategies: Delta vs Full firmware is one of the most practical design decisions you will make for any connected device, because it directly impacts bandwidth, failure rates and support cost. This comparison is for intermediate embedded and IoT engineers who already ship firmware and now want a clearer, more quantitative way to choose between delta (patch) updates and full image updates.

What you will get: a side-by-side comparison, sizing math, security and rollback considerations, and two working code examples (one for generating and applying delta patches, one for a resumable full-image downloader with integrity checking).

Table of Contents

OTA update strategies: Delta vs Full firmware

At a high level, you have two ways to deliver new firmware over-the-air (OTA):

  • Full firmware OTA: you download an entire new firmware image (or partition) and boot into it after verification.
  • Delta firmware OTA (also called patch-based OTA): you download a compact “difference” between the old and new firmware and reconstruct the new image on the device.

This choice is not only about “smaller download is better”. Delta updates can reduce network load dramatically, but they increase update complexity, require careful version management and can worsen failure handling if you do not design for resume and rollback. Full image updates are simpler and more robust across heterogeneous device states, but can be expensive on metered links and slow on constrained radios.

How delta and full OTA updates work

Full firmware update flow

  1. Device checks: device contacts your update service (HTTP(S), MQTT (Message Queuing Telemetry Transport), CoAP (Constrained Application Protocol) or vendor service) and asks for an update.
  2. Download: device downloads a complete image (often to an “inactive” partition).
  3. Verify: device verifies integrity (hash) and authenticity (signature).
  4. Swap: bootloader selects the new image (A/B scheme) or installs it in place (single-slot with staging).
  5. Commit or rollback: after successful boot and health checks, the device commits. If boot fails, it rolls back.

Diagram (described): Think of flash split into two equal “slots”, Slot A (active) and Slot B (inactive). You download to Slot B, verify, then set “boot next = Slot B”. If it boots and passes health checks, mark Slot B as “confirmed” and keep Slot A as rollback.

Delta firmware update flow

  1. Baseline identification: device reports its current firmware version and sometimes a build hash (not only a semantic version).
  2. Patch selection: server selects a patch that converts baseline X to target Y (X → Y).
  3. Download patch: device downloads the delta payload, typically much smaller than full image.
  4. Reconstruction: device applies the patch to the baseline image (or a copy) to produce the new image bytes.
  5. Verify and boot: same authenticity and integrity requirements as full OTA.

Key nuance: “delta” is not always “binary diff on the whole firmware”. You can implement deltas at different layers:

  • Binary image delta: diff the entire firmware image bytes.
  • Component delta: update only certain modules (for example, an app layer on top of an RTOS, web assets or ML models).
  • Block delta: patch only changed flash blocks, common in update frameworks that manage partitions.

Bandwidth, time and cost modeling

Use simple math to make the decision less emotional. Define:

  • S = full image size (bytes)
  • D = delta size (bytes)
  • R = effective throughput (bytes/sec), after protocol overhead and retransmissions
  • P_fail = probability of update failure (power loss, link drop, timeout) during the download+install window

Download time

T_full ≈ S / R

T_delta ≈ D / R + T_apply

Delta wins on time when D is much smaller than S and patch application time (T_apply) is small relative to download time.

Fleet bandwidth cost

For N devices updating once:

Data_full = N × S

Data_delta = N × D

If you pay for cellular data or satellite, this quickly dominates. On the other hand, on Wi-Fi or Ethernet it might not matter, so simplicity may dominate.

Failure risk window

Many failures correlate with time spent “in update mode”. A longer download and install window increases exposure to power loss and watchdog resets.

  • Full updates can have long download windows.
  • Delta updates can have additional compute and flash write windows (patch application) even if the download is short.

A practical rule of thumb

  • If your typical delta is < 30% of full image size and you can reliably identify the baseline, delta is often worth it.
  • If your devices have unknown drift (field repairs, partial updates, different optional features) then full OTA is often safer.

Flash layout, bootloader and rollback implications

Your bootloader and flash partitioning often decides what is feasible. The main patterns are:

A/B (dual-slot) with full image

  • Pros: best rollback story, simplest validation model, easy to resume download to inactive slot.
  • Cons: requires ~2x firmware storage plus metadata.

Single-slot with staging

  • Pros: less flash required than A/B.
  • Cons: more complex and riskier, you must avoid bricking during overwrite, often needs external flash or a reliable staging area.

Delta with A/B

  • Pros: you can apply patch to build the new image in the inactive slot, then verify and swap like full OTA.
  • Cons: you still need the inactive slot space, delta primarily saves bandwidth not flash.

Delta with single-slot (advanced)

  • Pros: can reduce bandwidth and keep minimal flash.
  • Cons: hardest to do safely. You need careful block-level journaling, power-fail safe patching or an external staging medium.

Practical guidance: If you cannot afford A/B slots in internal flash, consider adding external QSPI flash for staging, or choose full OTA but update a smaller “application” partition rather than a monolithic image.

Reliability, failure modes and resume

Both approaches must handle the same real-world problems: dead batteries, brownouts, network drops and corrupted storage. The difference is how many “moving parts” you add.

Common failure modes for full OTA

  • Interrupted download: fix with HTTP Range requests or chunked transfer, plus checkpointing.
  • Corrupt image: fix with per-chunk hashes and final image hash.
  • Bad boot: fix with A/B and boot attempt counters.

Common failure modes for delta OTA

  • Wrong baseline: device thinks it is on X but bytes differ, patch fails or worse, produces a wrong image. Fix with baseline hash, not only version numbers.
  • Patch apply interruption: fix with applying into inactive slot, or transactional patching with checkpoints.
  • CPU/RAM constraints: some patch algorithms need RAM buffers. Fix by choosing streaming-friendly patch formats.

Resume complexity

Full OTA resume often only needs “continue downloading from offset”. Delta OTA needs that plus “resume patch apply safely” if patching is not atomic.

Security and compliance considerations

Security requirements are similar for both approaches, but delta updates add extra pitfalls.

Minimum security requirements

  • Transport security: TLS for HTTP or MQTT over TLS, or OSCORE (Object Security for Constrained RESTful Environments) for CoAP.
  • Authenticity: sign update artifacts (full image or delta) using an asymmetric signature (for example, Ed25519 or ECDSA (Elliptic Curve Digital Signature Algorithm)).
  • Integrity: verify cryptographic hashes for the final reconstructed image, not only the downloaded artifact.
  • Anti-rollback: prevent downgrades unless explicitly allowed, using monotonic counters or version fuses.

Delta-specific security concerns

  • Patch correctness: attackers could attempt to craft a patch that triggers buffer overruns in your patch applier. Treat patch input as untrusted and fuzz test your patching code.
  • Reconstructed image verification: always verify a signature on the final image bytes (or verify a signed manifest that includes the final image hash). Do not trust “delta verified” as equivalent to “image verified”.
  • Baseline binding: bind the patch to a baseline hash (for example, SHA-256 of current slot) to prevent applying a patch to the wrong bytes.

Code example 1: Generate and apply delta patches

This example uses bsdiff/bspatch to generate a compact binary diff and apply it. This is a common pattern for delta OTA pipelines: your CI system produces a full image, then produces a delta against the previous release used by most of your fleet.

Step 1: Build two firmware images

You need two binaries: firmware_old.bin and firmware_new.bin. These could be raw images, UF2, Intel HEX converted to raw or a partition image. Delta works best when images are stable between builds, so avoid embedding build timestamps inside the binary if you can.

Step 2: Generate a patch (server or CI)

# Generates a delta patch using bsdiff (run this in CI or on your build server)
# Input: firmware_old.bin, firmware_new.bin
# Output: firmware_old_to_new.patch
set -euo pipefail

# Install tools (Ubuntu/Debian)
# sudo apt-get update && sudo apt-get install -y bsdiff

bsdiff firmware_old.bin firmware_new.bin firmware_old_to_new.patch

# Show sizes for a quick sanity check
ls -lh firmware_old.bin firmware_new.bin firmware_old_to_new.patch

Step 3: Apply the patch (device-side simulation)

On an embedded device you would run a patch applier as part of your update agent. Here is how to validate the pipeline locally:

# Applies a delta patch using bspatch
# Input: firmware_old.bin, firmware_old_to_new.patch
# Output: reconstructed_new.bin (should match firmware_new.bin)
set -euo pipefail

# Install tools (Ubuntu/Debian)
# sudo apt-get update && sudo apt-get install -y bsdiff

bspatch firmware_old.bin reconstructed_new.bin firmware_old_to_new.patch

# Verify reconstructed image matches the intended target
sha256sum firmware_new.bin reconstructed_new.bin
cmp -s firmware_new.bin reconstructed_new.bin && echo "Patch OK: images match"

How to map this to a real device:

  • Store the old image in Slot A, download the patch, reconstruct the new image into Slot B.
  • Compute SHA-256 of Slot B and verify it matches a signed manifest.
  • Swap boot to Slot B and commit after health checks.

When bsdiff is a poor fit: very constrained microcontrollers sometimes cannot afford the RAM or CPU for bspatch. In that case, use an update framework that supports streaming patch formats or do component-level updates (only patch a file system asset partition).

Code example 2: Resumable full firmware download with integrity

This example shows a practical full-image OTA downloader that supports resume via HTTP Range requests and verifies a final SHA-256. You can run it on a gateway, Linux-based device or as a reference implementation for your embedded update agent.

Step 1: Download with resume

# Resumable firmware downloader with SHA-256 verification
# Usage:
#   python3 ota_download.py https://example.com/fw.bin fw.bin <expected_sha256_hex>
import hashlib
import os
import sys
import requests

CHUNK = 1024 * 256

def sha256_file(path: str) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for b in iter(lambda: f.read(1024 * 1024), b""):
            h.update(b)
    return h.hexdigest()

def download_resume(url: str, out_path: str) -> None:
    existing = os.path.getsize(out_path) if os.path.exists(out_path) else 0
    headers = {"Range": f"bytes={existing}-"} if existing else {}

    with requests.get(url, stream=True, headers=headers, timeout=30) as r:
        if r.status_code not in (200, 206):
            raise RuntimeError(f"HTTP {r.status_code}")

        mode = "ab" if existing and r.status_code == 206 else "wb"
        with open(out_path, mode) as f:
            for chunk in r.iter_content(chunk_size=CHUNK):
                if chunk:
                    f.write(chunk)

def main():
    if len(sys.argv) != 4:
        print("Usage: python3 ota_download.py <url> <out_file> <expected_sha256>")
        sys.exit(2)

    url, out_path, expected = sys.argv[1], sys.argv[2], sys.argv[3].lower()

    download_resume(url, out_path)

    actual = sha256_file(out_path)
    if actual != expected:
        raise SystemExit(f"SHA mismatch: expected {expected}, got {actual}")

    print("Download OK and SHA-256 verified")

if __name__ == "__main__":
    main()

Step 2: Device-side mapping

  • Resume state: store the current downloaded size in a small metadata region, or infer it from the staging file size or slot write pointer.
  • Per-chunk hashes (recommended): store a manifest with chunk hashes to detect corruption early, especially on flaky links.
  • Signature verification: verify a signed manifest that includes the expected SHA-256 and version before swapping.

Platform and protocol fit (MQTT, HTTP, CoAP)

Protocol choice is often independent of delta vs full, but some combinations are easier to implement.

HTTP(S)

  • Full OTA: excellent fit, supports Range requests, caching, CDNs and straightforward scaling.
  • Delta OTA: also good, you download a patch artifact, same tooling as full images.

MQTT

  • Full OTA: you typically do not stream multi-megabyte binaries through MQTT brokers unless you control the full path and accept the cost. A common pattern is MQTT for signaling and HTTP for bulk download.
  • Delta OTA: same pattern, MQTT tells the device which patch URL to fetch.

CoAP

  • Full OTA: can work well in constrained networks, block-wise transfer helps, but tooling is less standardized than HTTP.
  • Delta OTA: feasible, but you must be more careful about patch-apply complexity on constrained nodes.

Decision matrix: what to choose

CriteriaDelta firmware OTAFull firmware OTA
Bandwidth usageBest when changes are small, often 5 to 30% of fullWorst, always 100% of image
Implementation complexityHigher: patch selection, baseline binding, patch apply safetyLower: download, verify, swap, rollback
Reliability across unknown device statesLower unless you strictly control baselines and driftHigher: fewer assumptions about current bytes
Flash requirementsOften similar to full if you still use A/B slotsHigh with A/B, medium with staging, lowest with risky in-place
CPU and RAM requirementsCan be significant depending on patch algorithmTypically lower and predictable
Security surfaceLarger: patch parser and apply logic needs hardeningSmaller: mostly download and signature verification
Best forCellular fleets, satellite links, very large images, frequent small releasesEarly-stage products, heterogeneous fleets, high reliability requirements

Practical recommendations

1) Start with full A/B OTA unless bandwidth is a top constraint

Full-image A/B updates are the simplest path to a robust updater: atomic swap, simple rollback and easy post-boot commit logic. If you are still stabilizing your product, this reduces the number of hard-to-debug “field-only” failures.

2) Add delta OTA when you have stable baselines and clear fleet version distribution

Delta starts paying for itself when most devices sit on a small set of known versions. Then your server can host a small number of patches, such as N-1 → N, and get most of the bandwidth savings without combinatorial patch explosion.

3) Avoid patch explosion with a patch policy

  • Adjacent-only patches: only generate patches from the previous release to the next (N-1 → N). Devices older than N-1 receive a full image.
  • Hub-and-spoke: pick a common baseline version B, generate patches B → target for a period, force older devices to update to B via full once.

4) Bind patches to immutable identifiers

In OTA update strategies: Delta vs Full firmware decisions, the most common delta failure is “wrong baseline”. Use a cryptographic hash of the current slot (or a build ID embedded in a signed manifest) to select patches safely.

5) Always verify the final reconstructed image

Even if your patch is signed, verify a signature or hash for the final image bytes that you will boot. This keeps your trust model consistent between delta and full OTA.

6) Measure real delta sizes before committing

Delta size depends heavily on how deterministic your builds are. If your build process injects timestamps, random IDs or reorders sections, your deltas may be large. Before you implement delta OTA in production, run a short experiment across 5 to 10 consecutive builds and record D/S ratios.

7) Use progressive rollout and health signals

Regardless of the approach, use staged deployments: update 1% of the fleet, then 10%, then 100% based on crash reports, boot confirmation rates and application-level health checks. This matters more than the delta vs full decision for overall fleet stability.

8) Combine strategies when it makes sense

You do not have to choose only one. Many successful systems use:

  • Full OTA for major releases and recovery
  • Delta OTA for frequent minor releases
  • Component updates for large data assets (web UI, certificates, ML models)

That hybrid approach often gives you the best tradeoff in OTA update strategies: Delta vs Full firmware planning without pushing complexity into every update.

Conclusion

OTA update strategies: Delta vs Full firmware is a trade between bandwidth and complexity. Full image OTA (ideally A/B) maximizes reliability and simplifies rollback, while delta OTA can dramatically reduce data usage when you control baselines and harden patch application. In practice, start with full OTA for robustness, then add delta for high-cost networks or high-frequency releases once you have stable versioning, signed manifests and a clear rollback plan.