One Millijoule at a Time: Firmware Delivery for Devices That Sleep Through the Year
Photo: Raimond Spekking, CC BY-SA 4.0, via Wikimedia Commons
Most OTA engineering advice assumes the device is listening. It has power, it has bandwidth, and the only real questions are when to push and how to roll back. For a growing class of hardware — BLE asset tags in a Chicago warehouse, soil moisture probes across a Nebraska corn field, smart locks on a thousand rental doors — that assumption collapses. These devices run on coin cells or small harvested energy reserves, and they spend most of their lives in a state closer to hibernation than operation.
For them, an update is not a background task. It is the single most expensive thing the device will do all year.
The Energy Math Nobody Shows You
Start with the numbers. A typical CR2032 cell delivers roughly 220 mAh at 3V — call it 2,300 joules of usable energy, and considerably less once you account for the voltage droop and the cold snap in a Minnesota January. A BLE peripheral downloading a 200 KB firmware image over a connection-event-driven link might expend 40 to 80 joules on radio time alone, before you count the flash writes, the CRC verification, and the reboot.
That doesn't sound fatal until you compare it against the device's normal duty cycle. A beacon that wakes weekly, advertises for 30 milliseconds, and sleeps again might burn 5 joules in an entire year. A naive full-image update just spent more than a decade of the device's operating budget in ninety seconds. And if the transfer fails at 90% — which it will, because these devices connect through hostile RF environments — you've paid that cost for nothing.
The first rule of power-aware OTA is therefore unforgiving: the download must be interruptible at any point, resumable, and never billed twice.
Delta Sizing Against a Joule Budget, Not a Byte Budget
Binary diffing is usually pitched as a bandwidth optimization. For energy-constrained fleets, it's a survival mechanism. But the framing has to change: instead of asking "how small is the patch," ask "does the patch fit inside the wake budget?"
That means working backward from the energy envelope. If a device can afford 2 joules per wake event and radio transmission costs roughly 10 microjoules per byte in your link budget, your practical ceiling is around 100 KB per wake — assuming you spend nothing else. A patch that requires three wake sessions to deliver is fine, provided the transport layer can persist partial state in flash without erasing and rewriting the same sectors each time.
Three practices make this workable:
- Compress deltas for the decompressor you already ship. Every byte saved on air is radio time, but exotic codecs cost CPU cycles, and on a coin cell, CPU time is energy too. Profile the whole chain, not just the download.
- Cap patch size at the firmware level. If a release produces a delta larger than the device's per-wake threshold, the pipeline should flag it before it ships — not after the fleet's batteries start dying in March.
- Stage flash writes in wear-aware blocks. A resumed download that rewrites the same page forty times is quietly destroying the storage you can never replace.
Dormant-Boot: Designing the Update Path for a Device That Is Mostly Off
Conventional bootloaders assume a device that powers on and stays on. A dormant device needs an update path that can make progress in fragments and survive being cut off mid-transaction without corruption — because there is no "staying up to finish."
The architecture that holds up in the field separates the update into three independent, individually atomic phases: metadata negotiation (cheap, done on any wake), payload transfer (interruptible, resumable, checksummed per chunk), and commit (a single, tiny, power-fail-safe swap of the boot pointer). The critical property is that a device that loses power during phase two boots normally into the old firmware and simply resumes later. There is no window where a dead battery bricks the unit.
This also changes how you think about the bootloader itself. It must be small enough and stable enough that it almost never needs updating — because updating a bootloader on a device with no power reserve and no wired fallback is a bet you cannot afford to lose. Some teams ship a bootloader and treat it as frozen for the product's entire life, routing every change through application-space indirection instead.
Coordinating With Wake Windows
A device that wakes once a week gives you 52 update opportunities per year, per device. Miss one and you're waiting. That arithmetic makes fleet-wide compliance a scheduling problem, and it's harsher than it looks.
The mechanics: when a device checks in, the server decides in real time whether this wake session should carry update traffic, based on the device's reported energy state (most battery fuel gauges can report voltage and estimated capacity cheaply), its link quality, and its position in the rollout cohort. A device reporting 2.7V on a 3.0V cell should defer — receiving a partial payload it can't finish is worse than waiting a cycle.
The uncomfortable consequence is that 100% fleet compliance takes time measured in weeks, not hours, and your progress dashboard needs to reflect that honestly. Push hard on low-battery devices and you'll trade update completeness for field failures — devices that die mid-cycle and never check in again. In an agricultural deployment, a dead sensor isn't a support ticket; it's a hole in a season's data.
The right metric isn't "how fast did we roll out." It's "how many devices are still alive and current." Those two numbers pull in opposite directions, and pretending otherwise is how fleets quietly lose 3% of their endpoints every major release.
Design for the Decade, Not the Deployment
Coin-cell and energy-harvesting hardware is moving from novelty to norm — smart building sensors, cold-chain tags, medical adherence monitors. The teams who treat OTA for these devices as a scaled-down version of a connected product's pipeline will keep discovering, one dead beacon at a time, that energy is the constraint that reorders every other decision.
Budget the joules. Make every phase of the update power-fail-safe. Schedule against wake windows, not release calendars. And measure success by the fleet that's still reporting a year later — because on these devices, the update that kills the battery is the last update you'll ever push to it.