OTA Updates Worked on Your Dev Kit. Now Ship Them to 10,000 Devices.

Your OTA demo was beautiful. BLE connected, the transfer bar crept to 100%, the device rebooted, the LED blinked green. Your PM clapped. Leadership asked “can we update the field?” and you said yes.
Now multiply that bench demo by 10,000 devices across three continents and six firmware versions. Add two hardware revisions, one with a slightly different flash layout that an intern introduced in rev C and nobody documented. Half are in warehouses with spotty Wi-Fi, a quarter are in consumer basements behind 2.4GHz microwaves, and a few thousand are bouncing around in trucks with dying batteries.
The gap between “OTA works” and “OTA works at scale” is where embedded products fail quietly, 18 months in, when an update ships and 2,000 devices never phone home again.
This piece is about what actually breaks when you move from ota update production fantasy to reality, and the questions you should be asking before the PCB goes to tape-out.
DEV KIT OTA PRODUCTION OTA
----------- --------------
1 device 10,000 devices
You watching Nobody watching
Wall power Dying batteries
Clean RF Microwave ovens
One firmware ver Six firmware vers
You can reflash You cannot reach itWhy Your Dev Kit OTA Lied to You
Your bench is a comfortable, productive lie.
On your desk you had perfect RF. One device. Wall power or a fresh battery. You were watching the serial console in real time. When something hung, you hit reset. When the image was corrupt, you reflashed over SWD. When the bootloader got confused, you erased the flash and started over.
None of that exists in the field. There’s no SWD pin in a customer’s garage.
Worse, your prototype quietly assumes things that break at scale. It assumes stable power throughout the transfer. A correct system clock for cert validation. Clean flash regions, a matching bootloader version, and a network path that stays up long enough to pull the image. Every one of those assumptions has a failure rate north of zero, and at scale, anything with a 0.1% failure rate happens to 10 devices on every update.
The bench hides concurrency too. Your server never had to answer 10,000 simultaneous image requests. Your BLE stack never had to handle a neighbor’s firmware update bleeding into your connection interval. You never saw what happens when the same device retries 400 times because it keeps losing the connection at 92%.
You built a proof of concept, and the mistake is thinking that’s the same thing as production OTA.
Interrupted Transfers and the Myth of “It’ll Just Retry”
BLE disconnects. Batteries die at 87%, users walk out of range mid-update, and a phone acting as gateway decides to update its own OS and drops the link.
The question you need to answer, honestly, is: what happens to the partial image?
If your answer is “the device retries from scratch next time,” you’re going to burn battery and customer trust. If your answer involves the word “probably,” you haven’t tested it. If you don’t know where the resume state lives (which flash sector, protected by what, written how atomically) you have a bug waiting.
Then there’s the flash layout fight: A/B (dual-bank) vs. single-bank with a swap. Single-bank is tempting because flash is expensive on constrained parts and you save ~50% of the footprint. It’s also how fleets get bricked. In single-bank, a power fail during the swap can leave you in a state the bootloader doesn’t recognize. In A/B, the worst case is “boot the old image, try again later,” which is almost always the behavior you want.
The uncomfortable reframe: your bootloader is your actual product. The app firmware is replaceable. The bootloader is not. If it has a bug, you have a paperweight. Code-review it like it’s going into a pacemaker. Fuzz it. Inject power failures during the swap, 1,000 times, on real hardware, not in simulation.
Here’s a concrete checkpoint: can a single device survive 1,000 interrupted updates, at random points in the transfer, without bricking once? If you haven’t run that test, you don’t know the answer.
Blast Radius: The Bad Update That Takes Down Your Fleet
The pattern is always the same. Update ships. Looks fine on 10 internal devices. Rolls out to 10,000. Somewhere in the telemetry path, 20 minutes later, someone notices the offline count climbing. A latent bug in power management, or a regression in the BLE connection parameters, or a subtle change in sleep timing. Now 2,000 devices won’t come back online long enough to accept the fix.
You can’t OTA a device that won’t connect.
The only defense is a real ota rollout strategy with health gates:
[Build] -> [Sign] -> [Canary 1%] -> [10%] -> [50%] -> [100%]
| | | |
health health health done
gate gate gate
|
FAIL -> auto-rollback, pause pipelineTwo things matter here that teams usually get wrong.
First, the canary cohort needs to be chosen for diversity, not convenience. Picking 100 devices in your office is not a canary. You want a mix of geographies, hardware revisions, firmware starting versions, and usage patterns. If your canary is all rev C boards on firmware 2.1 sitting on warehouse shelves, you’ll learn nothing about rev A boards on firmware 1.8 in a customer’s truck.
Second, automatic rollback needs to be tied to telemetry you trust: crash rate, connection success rate, battery drain delta vs. the previous version, time-to-first-checkin. The rollback trigger shouldn’t need a human to notice a dashboard at 3am.
A useful gut check: if you can’t pause a rollout in under 5 minutes from a laptop, you don’t have a rollout strategy, you have a cron job. Design the kill switch before you design the transfer.
Version Fragmentation Across Hardware Revisions
Rev A is in the field. Rev B fixed a power rail issue. Rev C, shipped last quarter, has a larger flash and an extra sensor. All three are live right now, and all three need to keep getting updates for the next 5 years.
One firmware binary per SKU doesn’t scale. Your build matrix explodes, your signing pipeline multiplies, your QA coverage per release drops. But one binary for all SKUs is impossible once the hardware actually diverges.
The answer is structural, and it has to be decided before manufacturing:
- The device must be able to read its own hardware revision from an immutable location at boot. GPIO straps, a fused OTP region, or a factory-written flash page. Not a sticker. Not a guess based on what sensors respond on I2C.
- The server must maintain a compatibility matrix: which firmware versions are valid for which hardware revisions. The device announces what it is; the server decides what it’s allowed to get. Never the other way around.
- Signing keys should be separated by environment (dev/staging/prod) and, ideally, by hardware generation. A leaked dev key shouldn’t brick prod. A compromised rev A key shouldn’t touch rev C.
The part that’ll sting: if rev A shipped without a way to read hardware ID from firmware, you can’t retrofit that over the air. You’re stuck treating rev A as a single fixed target forever, or you’re rolling trucks. Factory provisioning is where this gets baked in, and it’s the step teams routinely underfund. Our end-device provisioning guide covers the shape of this if you’re starting from scratch.
The Pre-Manufacturing Checklist
Take this to your next hardware review. Every “no” is cheap now and expensive later.
[ ] Dual-bank flash layout with verified bootloader
[ ] Cryptographically signed images (keys in HSM, not a laptop)
[ ] Hardware revision readable from firmware at boot
[ ] Resume-capable transfer protocol
[ ] Telemetry channel independent of OTA channel
[ ] Staged rollout mechanism with automatic rollback
[ ] Factory-provisioned device identity and keys
[ ] A way to recover a brick without physical access
[ ] Tested update path across every supported version combo
[ ] Power-fail injection test passing at 1000+ iterationsThe telemetry-independent-of-OTA one trips people up. If your only way to know a device is healthy is the same channel you use to update it, a bad update that breaks connectivity is invisible and unrecoverable. You need a heartbeat that works even when the main radio stack is sulking.
What “Good” Looks Like in Production
A healthy production OTA pipeline is boring, and that’s the goal.
An engineer pushes a signed build. CI runs it through dev, then staging, then a canary cohort picked for diversity. Dashboards show per-cohort health: crash rate, connection success, battery delta, time-to-checkin. A human approves the move from 10% to 50%. If any gate goes red, the pipeline pauses itself and pings the on-call. Rollback is one click and has been rehearsed.
The alternative, which is where most teams start, is “ship it and pray, then panic in Slack.” That works until your fleet is 500 devices. It stops working at 5,000. It destroys companies at 50,000.
Walk Into Your Next Design Review With These Questions
Every item on that checklist is cheap in schematic phase. Moderate in prototype. Expensive at DVT. Catastrophic post-manufacturing.
A missing hardware-ID pin is a $0 fix before tape-out. It’s a product recall after. A single-bank flash decision is a checkbox in your linker script today. It’s a fleet bricking event in 18 months. Signing infrastructure takes a week to do right now. It takes a security incident and a CVE to motivate later.
You don’t need a specific vendor to get this right. You need to walk into your next design review with these questions, and refuse to sign off until someone has an answer better than “we’ll figure it out in firmware.”
Hubble Network delivers OTA updates to devices anywhere on Earth over Bluetooth, without the cellular modems, Wi-Fi credentials, or gateway infrastructure that break fleet updates at scale. See how it works →