LoRaWAN FUOTA: Firmware Update Over the Air with Multicast, Fragmentation and Clock Sync (2026)

LoRaWAN FUOTA: Firmware Update Over the Air with Multicast, Fragmentation and Clock Sync (2026)

LoRaWAN FUOTA: Firmware Update Over the Air with Multicast, Fragmentation and Clock Sync (2026)

A LoRaWAN sensor typically gets a few hundred bytes per day of downlink capacity and a 10 percent radio duty-cycle budget on the best sub-band. A modest firmware image is a hundred kilobytes. Put those two facts together and the naive plan, sending the image to each device with ordinary unicast downlinks, collapses into days of airtime per device and a gateway that cannot do anything else. Yet fleets of thousands of battery sensors do get patched in the field, and they do it in hours, not months.

LoRaWAN FUOTA (firmware update over the air) works because three small application-layer protocols from the LoRa Alliance cooperate: clock synchronization so every device agrees when to listen, remote multicast setup so one transmission reaches a whole group, and fragmented data block transport with forward error correction so lost packets do not force retransmission. This article builds the whole pipeline from first principles, with worked airtime numbers, a runnable planner, and the failure modes that actually hurt.

What this covers: the three FUOTA building-block specifications and what each message does, how Class B and Class C multicast sessions differ, how parity fragments are used, airtime and duty-cycle arithmetic for a 100 KiB image at three data rates, the network and application server roles, image signing and bootloader rollback, delta updates, how this compares with NB-IoT and LTE-M, and where it goes wrong.

Context and Background

LoRaWAN was designed for devices that send small uplinks rarely and listen only briefly afterwards. A Class A end device opens two short receive windows after each uplink and is otherwise deaf. That is what makes ten-year battery life plausible, and it is also why firmware updates were an afterthought in early deployments: if you cannot talk to a device when you want to, you cannot push a large payload to it.

The operational pressure to fix that came from the field. Sensors deployed for utilities, agriculture and smart buildings live for a decade, while security fixes, radio parameter bugs and protocol revisions arrive every year. Truck rolls to reflash a device with a cable cost far more than the device. The LoRa Alliance’s answer was not to change the MAC layer but to standardize a set of application-layer packages that run on top of it. The Alliance publishes them together as the building blocks for FUOTA: Application Layer Clock Synchronization (TS003), Fragmented Data Block Transport (TS004) and Remote Multicast Setup (TS005). Its FUOTA building-block page lists v2.0.0 of all three, and implementations in the wild still ship v1 revisions, so always check which version both ends speak. Open-source firmware stacks make the picture concrete: the Zephyr LoRaWAN FUOTA sample implements clock sync, remote multicast setup and fragmented data block transport, runs the process in a background work queue, and hands over to MCUboot to apply the image when the last fragment arrives.

It is worth being precise about what the standard does not cover. The three specifications define how bytes get from a server to a group of devices reliably. They do not define the image format, the signature scheme, the bootloader, version policy or which devices should be updated when. Those belong to your device firmware and your fleet management layer. That is where most real FUOTA incidents originate, and why this article spends as much time on signing and rollback as on radio.

Device support is also optional. The ChirpStack documentation says plainly that FUOTA support on the device is optional and that you should assume a device does not support it unless its documentation says otherwise. If you are still choosing radios for a project, our guide to Wi-Fi HaLow versus LoRaWAN versus LTE-M frames when LoRaWAN is the right bearer in the first place. If your fleet spans multiple radios, the update-framework question is broader, and we compare options in SUIT, Uptane and Mender versus RAUC and SWUpdate.

Throughout this article, numbers labelled illustrative are my own computations from stated assumptions, not measurements from a particular network. They are meant to show orders of magnitude and how the levers interact.

The FUOTA Reference Architecture

FUOTA is a pipeline of five stages. A server prepares a signed image and splits it into fragments, an application server tells devices when and where to listen, the network server schedules identical multicast downlinks through every gateway that covers the group, devices collect and repair the fragments, and a bootloader verifies and installs the result. Three LoRa Alliance packages carry the coordination.

LoRaWAN FUOTA reference architecture showing application server, network server, gateways, Class C multicast group and bootloader

Figure 1: FUOTA reference architecture. The application server drives the three packages, the network server schedules multicast, and the device owns reassembly, verification and install.

Figure 1 shows the data path left to right and the control feedback as dashed lines. The key idea is that the downlink path is one-to-many and has no acknowledgements at all. Everything that needs a reply, such as session status or missing fragment reports, happens afterwards on ordinary Class A uplinks.

Three packages, three fixed ports

Each package is a small command protocol carried in the FRMPayload of normal LoRaWAN frames on a dedicated application port. As I understand the specifications, clock synchronization uses port 202, remote multicast setup uses port 200, and fragmented data block transport uses port 201, and the package identifiers are 1, 2 and 3 respectively. Treat those numbers as defaults to confirm against the specification revision you implement, because the ports are the first thing to check when a device ignores your commands.

The division of labour is clean. Clock sync answers the question “what time is it?” to roughly one second. Multicast setup answers “which group, which keys and when do I switch to continuous listening?” Fragmentation answers “how big is the image, how is it split and how do I tell you what I am missing?” The three never depend on one another at the byte level, but a session needs all three to be correct.

Why multicast is the whole point

A multicast group is a set of devices sharing a multicast address and a pair of session keys that are not tied to any single device’s join. A gateway transmits one downlink frame to that address and every member in range receives the same bits. For a fleet of one thousand devices, this is the difference between one thousand times the airtime and one times the airtime plus a little repair traffic.

The price is that multicast cannot be acknowledged and cannot use adaptive data rate per device. The data rate is chosen once for the whole group, so it has to be one that the worst device in the group can decode. That single parameter drives the whole airtime budget and is the reason a FUOTA plan begins with a coverage survey, not with a script.

Class C versus Class B sessions

A multicast session must happen while devices are listening, and Class A devices are not. The remote multicast setup package therefore asks a device to switch temporarily to Class C or Class B for the length of the session. In LoRaWAN Class C operation the device keeps its receiver open continuously except while transmitting, so the network can send a multicast frame at any moment inside the session. That is simple and fast, and it is expensive for the battery, because the receiver draws current for the entire session.

Class B devices instead synchronize to periodic gateway beacons and open short, scheduled ping slots. They listen for a small fraction of the session, which is far kinder to batteries, but the session lasts much longer and it requires both devices and gateways to support beaconing. ChirpStack’s FUOTA guide advises selecting Class B only if the devices and gateways support it, which in practice means Class C is the default for most deployments and Class B is the right answer when end devices are battery powered with no mains alternative. A third consideration is that mains-powered devices can simply stay in Class C continuously, in which case the session can start at any time.

The control message sequence

Figure 2 shows one complete FUOTA session as a sequence.

LoRaWAN FUOTA sequence diagram of clock sync, multicast setup, fragmentation session setup, Class C session and status reporting

Figure 2: One FUOTA session end to end. Control happens on Class A uplink and downlink windows, the bulk transfer happens in the multicast window, and repair happens afterwards.

First the application server checks that the device clock is close enough to GPS time. It then installs a multicast group on each device, opens a fragmentation session with the image geometry, and finally tells the group when to switch to Class C and for how long. Only then do the fragments flow. When the session ends, devices fall back to Class A and report their status.

The long description matters because it contains the design’s central trade: all the expensive control traffic is unicast and happens before the session, and all the bulk data is multicast and happens inside it. Reliability for the bulk phase comes from the fragment code, not from retransmission.

Deeper Analysis: Clock Sync, Multicast Setup and Fragmentation

Clock synchronization is a scheduling problem, not a luxury

A multicast session starts at an absolute time. The setup command carries a session start time expressed as seconds since the GPS epoch, 6 January 1980, which is how LoRaWAN Class B and the clock sync package express time. If a device believes it is later than it is, it will open its receiver after the first fragments were already sent. If it believes it is earlier, it listens longer than necessary and burns battery. Either way, the precision of the clock decides the cost of the session.

The Application Layer Clock Synchronization package is deliberately simple. The device sends an AppTimeReq containing its current time estimate and a token. The server replies with an AppTimeAns carrying a signed correction in seconds, and the device adds the correction to its clock. The package’s resolution is one second, and a paper surveying FUOTA in the Journal of ICT Standardization describes the best achievable accuracy as around a second, because the exchange rides on Class A uplink and downlink timing rather than on a dedicated time reference.

That sounds coarse, but it is enough once you compute drift. A typical low-cost crystal is specified at tens of parts per million. At 20 ppm, which is an illustrative but common figure for uncompensated crystals, the clock drifts 20 microseconds per second, or about 1.7 seconds per day. If a device synchronised a week ago, the error could be 12 seconds. A device with a 32.768 kHz watch crystal is better, and a device whose application resynchronises daily is better again, but the conclusion is the same: the planner must give every device a guard interval at the start of the session that is larger than its worst-case drift since its last sync.

Two operational rules follow. First, run a clock sync round for every device immediately before scheduling a session, not weeks earlier at provisioning. The extra uplink is cheap compared with a failed session. Second, schedule the session start far enough in the future that the setup commands themselves, which are Class A downlinks that wait for an uplink to be opened, have time to reach every device. In a fleet where devices uplink once an hour, a session that starts in ten minutes will simply exclude most of the group.

Remote multicast setup: the group, the keys, the session

The remote multicast setup package is the control plane for the group. As defined in the package, the server sends a group setup command containing a group identifier, a multicast address, the group session key delivered in encrypted form, and a minimum and maximum frame counter. The encrypted key is protected so that an observer of the setup downlink does not learn the multicast session key. The frame counter range gives the device a replay window: multicast frames outside it are discarded, and a new session needs a new range.

Then comes the session command. For Class C, the server sends a class C session request containing the group, the session start time, a timeout expressed as a power of two in seconds, the downlink frequency, and the data rate. For Class B the equivalent command adds a ping slot periodicity. Both define where the device must listen, so the server has total control over the radio parameters of the session and can place it on a frequency that is not being used for ordinary Class A second receive windows.

That last point matters operationally. In the EU868 plan, the default second receive window for many networks sits at 869.525 MHz, and that sub-band is commonly regulated with a 10 percent duty cycle. If your multicast session runs on the same frequency, every second-window downlink for ordinary devices must wait behind it. The better practice is to choose a dedicated multicast frequency and make sure the gateway can transmit there. Check your regional parameters and local regulation; I am describing the typical EU case, not giving legal advice.

The setup command also fixes the timeout. Because the session timeout is encoded as a power of two, you cannot tune it precisely; you choose the next larger value. ChirpStack exposes this as an option to calculate the multicast timeout from its settings and the number of multicast fragments, which is a sensible default because a hand-entered value is a common source of devices that fall back to Class A seconds before the final fragments are sent.

Fragmented data block transport

The firmware image is a data block. Fragmented data block transport defines how to split a block of M fragments of equal size, transmit them with extra parity fragments, and reassemble them on the device. The session setup command carries the number of fragments, the fragment size in bytes, a control field including the algorithm and the block acknowledgement delay, the padding length for the last fragment, and a four byte descriptor which applications often use to carry a version or hash prefix. A device can hold more than one fragmentation session, identified by a small index, and the session carries its own numbering.

Each data fragment message contains a header with the fragmentation index and a fragment counter, then the payload. Because the counter is 14 bits wide, a single session can address up to 16,383 fragments, plenty for LoRaWAN images but a hard ceiling to remember if you shrink fragment sizes at low data rates. Fragments 1 to M are the source data in order. Fragments above M are parity.

Fragmentation and forward error correction flow for LoRaWAN FUOTA with missing fragment feedback loop

Figure 3: Fragmentation with forward error correction. Parity fragments let the device solve for lost source fragments; if it still cannot, it reports a missing-fragment bitfield and the server sends more parity.

How the parity matrix works

Forward error correction in this specification is a systematic linear code. Each parity fragment is the bitwise XOR of a pseudo-randomly chosen subset of the source fragments. The choice of subset is a deterministic function of the fragment index, produced by a small pseudo-random generator defined in an annex of the specification, so the device can recompute the same subset locally without any additional data being sent. This is the property that makes a parity fragment worth more than a retransmission: a single parity fragment can repair any one of many different lost fragments, depending on which others the device already holds.

On the receiving side every received fragment, source or parity, is one linear equation over the unknown source fragments. The device keeps a binary matrix of the equations it has and solves it incrementally. When the matrix has enough independent rows to determine all M unknowns, the image is complete. The exact generator and density are specified in the Alliance document and my description is the conceptual model, not the bit-level procedure, so use a vetted implementation such as the reference decoder shipped with Semtech’s LoRaMac-node or your SDK rather than rewriting it.

Two properties are worth internalising. First, because the code is systematic, a device that receives every source fragment never needs any parity. Redundancy is insurance that costs airtime whether or not it is used. Second, a random sparse code is not perfectly efficient: you need slightly more than M received fragments on average to be able to solve, and the shortfall varies. Planning with a pure “M out of N” model understates the redundancy you need, which I handle in the next section with an explicit overhead allowance.

Worked Airtime and Duty-Cycle Budget for a 100 KiB Image

All numbers in this section are illustrative computations under stated assumptions, not field measurements. I assume an EU868 style plan, 125 kHz bandwidth, coding rate 4/5, an eight symbol preamble, CRC on, and 13 bytes of LoRaWAN overhead per frame. I take the maximum application payload per data rate as 51 bytes for DR0, 115 bytes for DR3 and 222 bytes for DR5 (the repeater-compatible figures; larger values are allowed when no repeater is in the path). Each fragment loses 3 bytes to the fragmentation header, and the 100 KiB image is 102,400 bytes. The multicast channel is assumed to be limited to a 10 percent duty cycle.

Multicast data rate Fragment payload Source fragments M Fragment airtime 10% redundancy total airtime Wall-clock at 10% duty cycle
DR0, SF12 48 B 2,134 about 2.79 s about 109 min about 18.2 h
DR3, SF9 112 B 915 about 0.68 s about 11.4 min about 1.9 h
DR5, SF7 219 B 468 about 0.37 s about 3.2 min about 32 min

The spread is enormous. The same image takes about half an hour at SF7 and most of a day at SF12, a factor of roughly 34 in wall-clock time, because both the airtime per frame and the number of frames change. The lesson is that the worst-covered device in the group sets the data rate for everyone, so a single device behind a thick wall can turn a thirty minute update into an overnight one. A common mitigation is to build the multicast group by coverage class, one group per spreading factor band, or to improve gateway placement first.

Now add redundancy. Suppose each multicast fragment is lost independently with probability p at a given device. With N total fragments and M needed, the probability that a device receives at least M of N is a binomial tail. The next table uses the DR5 case with M = 468 and shows two readings: the ideal case where exactly M received fragments suffice, and a pessimistic case where M + 10 are needed to allow for an imperfect sparse code. The overhead of ten is an assumption for illustration.

Redundancy Total N Loss 5%, ideal / M+10 Loss 10%, ideal / M+10 Loss 15%, ideal / M+10
5% 491 0.43 / 0.01 0.00 / 0.00 0.00 / 0.00
10% 515 1.00 / 0.99 0.28 / 0.02 0.00 / 0.00
15% 538 1.00 / 1.00 0.99 / 0.83 0.11 / 0.01
20% 562 1.00 / 1.00 1.00 / 1.00 0.88 / 0.51

The cliff is sharp. At 10 percent loss, going from 10 to 15 percent redundancy moves the success probability from near zero to near certainty. This is the central design fact about forward error correction: below the loss rate it does almost nothing, and just above it it does almost everything. So the redundancy setting is a bet on the measured loss rate of the worst devices, and a fleet-wide first pass will always leave a tail of devices that need repair.

A runnable fragment planner

The script below reproduces the tables. It computes LoRa airtime from the Semtech formula, finds the smallest number of total fragments N for which a device meets a target success probability, and converts airtime into wall-clock time under a duty-cycle limit.

import math

def lora_airtime(app_payload, sf, bw=125_000, cr=1, preamble=8, crc=True, implicit=False):
    pl = app_payload + 13                      # MHDR+DevAddr+FCtrl+FCnt+FPort+MIC
    de = 1 if (sf >= 11 and bw == 125_000) else 0
    t_sym = (2 ** sf) / bw
    num = 8 * pl - 4 * sf + 28 + (16 if crc else 0) - (20 if implicit else 0)
    n_pay = 8 + max(math.ceil(num / (4 * (sf - 2 * de))) * (cr + 4), 0)
    return (preamble + 4.25 + n_pay) * t_sym

def p_at_least(n, k, q):
    total = 0.0
    for i in range(k, n + 1):
        total += math.exp(math.lgamma(n+1) - math.lgamma(i+1) - math.lgamma(n-i+1)
                          + i*math.log(q) + (n-i)*math.log(1-q))
    return total

def plan(image_bytes, sf, max_app_payload, loss, target=0.99, overhead=10, duty=0.10):
    frag_size = max_app_payload - 3            # CID + 2-byte Index_and_N
    m = math.ceil(image_bytes / frag_size)
    n = m
    while p_at_least(n, m + overhead, 1 - loss) < target:
        n += 1
    toa = lora_airtime(max_app_payload, sf)
    return dict(frag=frag_size, M=m, N=n, redundancy=f"{(n-m)/m:.1%}",
                toa_ms=round(toa*1000), airtime_min=round(n*toa/60, 1),
                wall_min=round(n*toa/duty/60, 1))

for label, sf, mx in [("DR0 SF12", 12, 51), ("DR3 SF9", 9, 115), ("DR5 SF7", 7, 222)]:
    print(label, plan(100*1024, sf, mx, loss=0.10))

Running it with 10 percent loss, a 99 percent per-device target and the ten fragment overhead allowance gives redundancy of about 13 percent at SF12, 15 percent at SF9 and 17.5 percent at SF7. At SF7 that means 550 fragments, about 3.4 minutes of airtime and about 34 minutes of wall-clock time at the 10 percent duty cycle. The redundancy percentage is lower at SF12 only because there are many more fragments and the law of large numbers tightens the spread. Changing the loss assumption to 20 percent at SF7 raises the plan to 627 fragments, 34 percent redundancy and about 38.5 minutes.

Note what the script does not model: correlated loss. Real interference arrives in bursts, and a device that sits in a deep fade for ten seconds loses a run of consecutive fragments. Sparse random codes handle burst erasures well because every parity fragment mixes pseudo-random source fragments, but the independent-loss binomial is still optimistic. Treat the output as a lower bound and verify with a pilot group.

Server Roles: Network Server, Application Server and the FUOTA Service

FUOTA is split across two server roles that are easy to blur. The network server owns the radio: it knows which gateways cover which devices, schedules downlinks, tracks duty cycle per gateway and manages multicast groups at the MAC level. The application side owns the semantics: it builds the fragmentation plan, sends the package commands, decides when a device counts as updated, and tags the result.

In ChirpStack this separation is explicit. A separate FUOTA server component implements the three packages and talks to ChirpStack’s API to create multicast groups and enqueue multicast downlinks. The deployment form exposes the knobs that matter: a unicast retry count for the control commands, a multicast group type that selects Class B or Class C, a fragmentation redundancy setting that the documentation recommends enabling, an option to calculate the multicast timeout automatically, and an option to use the largest fragment size permitted by the device profile’s regional parameters revision. The regional parameters revision therefore influences the fragment size, which is another reason to keep device profiles accurate. The FUOTA documentation also describes optional device tags applied on completion, such as a firmware version tag you can later filter on.

Managed cloud services follow the same shape. AWS IoT Core for LoRaWAN documents a FUOTA workflow built around multicast groups and update tasks, although I did not verify the current limits or supported device classes for this article, so check the vendor’s page before planning around it. The Things Stack’s support for the FUOTA packages and multicast is something I also did not verify for this post; check its current documentation if you depend on it.

Whichever platform you use, ask four questions of it. Can it schedule multicast on every gateway in coverage with identical timing? Does it let you choose the multicast frequency and data rate? How does it deal with a gateway that has run out of duty-cycle budget? And does it keep a per-device record of fragmentation status so you can target repair?

The gateway is a shared resource

During a multicast session, each participating gateway is transmitting continuously at its duty cycle ceiling. In a dense deployment, that crowds out ordinary downlinks that share the gateway’s transmit budget: confirmed uplink acknowledgements, MAC commands, and join accepts for new devices. A 30 minute session at SF7 is tolerable; an 18 hour SF12 session is an outage for everything else on that gateway’s sub-band. Schedule multicast in quiet hours, use a separate frequency, and keep the group small enough to finish within a window you can afford.

For large fleets the answer is geographic partitioning. Update a region at a time, with gateways in each region transmitting the same fragments at the same time, and stagger regions so that you never lose more than a fraction of coverage if a bad image reaches the field. This is the same blast-radius logic that applies to any rollout.

Status feedback and repair

After the session, the fragmentation package defines a status request and answer. The device reports how many fragments it received, a bitfield or count of what is missing, and an overall status that distinguishes complete, incomplete and error states such as a failed integrity check. The server can use the missing information to decide whether to send another multicast burst with fresh parity fragments or to repair a handful of devices by unicast.

Devices do not all answer at once. A block acknowledgement delay parameter in the session setup makes each device wait a randomised interval before sending its status, which prevents a thousand devices from colliding in the same uplink slot. That randomisation matters more than it looks: a synchronised status storm on a few gateways looks exactly like a denial of service against your own network.

Image Signing, Bootloaders and Rollback

The radio layer delivers bytes. It does not tell you whether the bytes are a legitimate image, and the fragmentation package is not an authentication mechanism. If you want secure FUOTA, authenticity must be enforced at the image level by the bootloader, using a signature that the device can verify with a public key held in its immutable boot stage.

The pattern I recommend is the one used by MCUboot. The build system signs the image with a private key that never leaves your build infrastructure. MCUboot, a widely used open-source secure bootloader for microcontrollers, verifies the signature of the image in the secondary slot before it swaps it into the primary slot; it supports ECDSA over P-256, RSA and Ed25519 signature schemes, though you should confirm the algorithms your port enables. A swap with test mode installs the new image provisionally. If the application does not mark the image as confirmed after it boots and passes a self-test, the next reset reverts to the previous image. That confirm-after-health-check step is what turns a bricked field device into a transient failure.

Failure and rollback decision flow for LoRaWAN FUOTA covering clock drift, packet loss, signature validation and boot self-test

Figure 4: Where a FUOTA session fails and what catches each failure. Clock drift and loss are radio problems; signature and self-test are image problems with separate defences.

Several other controls belong in the image pipeline. Include a monotonically increasing version number in the signed metadata and reject downgrades unless a signed override is present, otherwise an attacker who can replay old fragments can force a known-vulnerable build. Bind the image to a hardware family so that a sensor image is not accepted by a different board. Put an integrity hash in the fragment descriptor, which is a convenient place for a short identifier, so the application can discard a mismatched session before the expensive reassembly.

On devices with secure elements or a TPM-class root of trust, the signing key verification can be anchored in hardware and the measurement of the booted image can be attested, as described in our article on TPM 2.0, secure boot, measured boot and remote attestation for IoT fleets. Most LoRaWAN-class microcontrollers lack a TPM, so the realistic baseline is a signature check in a locked boot stage plus a write-protected bootloader region.

Storage is the other practical constraint. A swap-based scheme needs room for two full image slots plus scratch or trailer space, so a 100 KiB application on a 256 KiB flash part can be tight. Partition planning needs to happen before you ship the first unit, because changing the layout later is itself a bootloader update, and that is the one update you cannot safely do over the air without a recovery path.

Delta updates

A delta update sends only the difference between two images. With a reasonable diff algorithm the patch for a minor change can be a fraction of the full image. As an illustration only, suppose a patch is 20 KiB for a 100 KiB image. At DR5 with the same redundancy assumptions, that is 94 source fragments and about 125 total fragments for a 33 percent allowance at a 10 percent loss target, roughly 0.8 minutes of airtime or under 8 minutes of wall-clock time, compared with about 34 minutes for the full image.

The saving is real, and so is the risk. A delta applies only to one exact source version. If any device in the group is on a different base version, the patch produces garbage, and the signature check on the reconstructed image will fail only after you have spent the airtime. Fleets of mixed versions need either multiple delta groups or a fallback to full images. Delta decoding also needs a bit of RAM and flash scratch on the device, and bootloader support for applying the patch in place, which is not universal. For many projects the best use of deltas is to keep full images small and well-compressed first.

Comparing with NB-IoT and LTE-M Over-the-Air Updates

Cellular LPWAN bearers solve firmware delivery with a very different mechanism. NB-IoT and LTE-M devices have an IP-capable data path, so they download firmware over a unicast connection using protocols such as HTTPS, CoAP block-wise transfer or LwM2M’s firmware update object. Each device pulls its own copy, with transport-level reliability and flow control, at data rates that are orders of magnitude higher than LoRaWAN’s. A 100 KiB image fetches in seconds to minutes depending on the bearer and coverage, billed against the device’s data plan.

Property LoRaWAN FUOTA NB-IoT or LTE-M OTA
Delivery model Multicast broadcast, no per-device acknowledgement Unicast pull per device
Reliability mechanism Parity fragments plus repair rounds Transport retransmission
Cost scaling with fleet size Nearly flat for airtime, plus repair Linear in devices times image size
Time for 100 KiB Tens of minutes to many hours Seconds to minutes (typical, varies with coverage)
Infrastructure Private or public LoRaWAN network and gateways Operator network and data plan
Device energy Long continuous listening in Class C Short connected burst
Operational complexity High, you own the session choreography Lower, standard IP tooling

Neither wins on every axis. For a dense fleet in one area, multicast is much cheaper than paying for every device to download its own copy on a metered plan. For a sparse, geographically scattered fleet, cellular’s per-device pull is simpler and faster. 3GPP has also defined multicast mechanisms for its IoT bearers in later releases, but I have not verified how widely operators deploy them, so I would not plan a design around them. The deciding factors are usually fleet density, backhaul ownership and update frequency, not raw throughput.

Trade-offs, Gotchas, and What Goes Wrong

The first and most common failure is a device that never joins the session. The device has the packages disabled, uses the wrong port, runs an older package version than the server, or its clock drifted outside the guard interval. These show up as a missing status answer. Always check capability and clock before the session, and keep a per-device log of the setup acknowledgements, because a lack of acknowledgement is the first evidence.

The second is the battery cost. In Class C, the radio stays in receive for the whole session. As an illustrative figure, if the receiver draws roughly 5 mA, an 18 hour SF12 session consumes about 90 mAh, several percent of a small primary cell, and a 34 minute SF7 session consumes about 3 mAh. Real current depends on the radio and the rest of the board, which is likely to add more than the receiver. Battery devices should therefore use Class B or a short session at a robust data rate, and any plan should include an estimate of the energy budget per update against the battery’s remaining headroom.

Third, loss is not uniform. The device at the edge of coverage needs the most redundancy and sets the data rate. Pushing a fleet-wide session at the rate its median device supports and then discovering that 8 percent of devices never complete is the typical outcome of skipping the coverage survey. Run the first session on a pilot group and measure completion before scaling.

Fourth, bad images. A session can finish correctly and still deliver a broken firmware. Without confirm-after-test and rollback, the whole fleet can be bricked by one bad release, and a bricked LoRaWAN device is by definition one you cannot talk to. Staged rollout, health checks and an automatic revert are not optional.

Fifth, duty-cycle accounting. If the network server’s duty-cycle model and the gateway’s actual limit disagree, one of them will violate the regulation or silently drop frames. Test the whole path with a spectrum monitor or a packet capture before running at scale.

Finally, security is an end-to-end property. The fragments are multicast under shared group keys, so anyone who can obtain the group key can inject frames that look valid to the radio layer. Only the signature check on the reassembled image stops a malicious update, which is why the check belongs in the immutable boot stage and not in application code that the attacker is trying to replace.

Practical Recommendations

Start by treating FUOTA as a fleet operation, not a feature. The protocol work is a small part of the effort; the larger part is building a pipeline that signs images, plans sessions by coverage, runs staged rollouts and rolls back safely. A good first milestone is a signed image delivered to ten bench devices with an induced bad-image rollback test.

Choose the multicast data rate from measurements. Pick the slowest rate you will tolerate for the worst device you care about, compute airtime and duty-cycle wall-clock time with a script like the planner above, and compare it with your maintenance window. Set redundancy a few points above the measured loss, because the success curve is a cliff. Plan one repair round by default.

Use Class C only where you can afford it. Put mains-powered devices in Class C groups and battery devices in separately scheduled Class B groups if their hardware supports beaconing. Keep sessions short, keep images small, and prefer a delta only after you can guarantee base-version uniformity.

A checklist before the first production session:

  • Confirm each device supports clock sync, multicast setup and fragmentation, and which package versions.
  • Resynchronise clocks within the last day and set a guard interval above worst-case drift.
  • Put multicast on a dedicated frequency and verify the gateway duty-cycle budget.
  • Group devices by coverage class and choose one multicast data rate per group.
  • Compute fragments, redundancy and wall-clock time with a planner; add a repair round.
  • Sign the image, embed a version, enforce no-downgrade, and test rollback on bench units.
  • Pilot on 1 to 5 percent of the fleet and measure completion before widening.
  • Stagger status replies and monitor the uplink load on gateways.
  • Record per-device outcomes and retire devices that fail twice for manual inspection.

Frequently Asked Questions

What is LoRaWAN FUOTA?

LoRaWAN FUOTA is firmware update over the air using three LoRa Alliance application-layer packages: clock synchronization, remote multicast setup and fragmented data block transport. The server sets up a multicast group, tells devices when to switch to Class C or Class B, and broadcasts the image as fragments with parity so devices can repair losses. A bootloader then verifies and installs the result.

How long does a LoRaWAN firmware update take?

It depends almost entirely on data rate and image size. In an illustrative EU868 calculation with a 10 percent duty cycle, a 100 KiB image takes about half an hour at SF7 and most of a day at SF12, with 10 percent redundancy assumed. Delta updates, better gateway placement and a higher multicast data rate are the main levers for shortening it.

Why does FUOTA use multicast instead of unicast?

Multicast sends each fragment once and every device in the group receives it, so airtime stays roughly constant as the fleet grows. Unicast would multiply airtime by the number of devices and would also need per-device downlink opportunities, which Class A devices rarely offer. The trade-off is no per-frame acknowledgement, which is why fragmentation includes forward error correction and a status phase.

Do I need Class C for FUOTA?

Devices must be listening when fragments arrive, so they need either Class C or Class B for the session. Class C is simpler and faster but keeps the receiver open for the whole session. Class B saves energy by using scheduled ping slots but needs beacon support in devices and gateways and stretches the session. Mains-powered devices usually use Class C.

How is a FUOTA image kept secure?

The transport layer does not authenticate the image, so security relies on signing the firmware and verifying it in the bootloader. MCUboot-style bootloaders check a signature against a public key stored in the boot stage, enforce version numbers to block downgrades and support test-boot with automatic rollback if the new image does not confirm itself. Group keys alone are not sufficient protection.

What happens if some fragments are lost?

Parity fragments let a device reconstruct missing source fragments as long as it receives somewhat more than the number of source fragments. If it still cannot, it reports its missing fragments in a status answer and the server sends more parity fragments in another multicast round or repairs individual devices by unicast. Planning redundancy just above the measured loss rate avoids most repair rounds.

Further Reading

By Riju — about

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *