ZeroTrace AirLeak
Why ESP32-S3?
Why we picked an older chip over the newer ESP32-C5, a workload-driven decision, not a marketing one.
The ESP32-C5 is newer. On a spec sheet it looks like the obvious upgrade, 5 GHz Wi-Fi 6, Bluetooth 5.2, "next-generation" framing in the marketing. We went with the older ESP32-S3 anyway. This page explains why, in detail, and exactly what the trade-off is.
The short version: AirLeak's bottleneck is CPU and memory, not radio. Every "next-gen" feature on the C5 spec sheet is irrelevant to that bottleneck, and several of the things we do depend on regressed in the C5.
The actual workload
AirLeak's job, simplified:
- Receive every BLE advertisement in the air via a continuous NimBLE observer scan.
- Decode each one (parse vendor-specific blobs, Apple Continuity, Find My, FMDN, Eddystone, Fast Pair, Tile, Samsung SmartTag, Microsoft Swift Pair).
- Aggregate into a per-device state machine, run classification + leak heuristics.
- Coalesce per-device changes into a CBOR delta stream and notify the mobile app over a dedicated BLE characteristic in real time, while simultaneously holding that connection and continuing to scan.
In a moderately busy room (think coffee shop, office, transit hub) the advertisement decode path runs hot, with bursts during the scan-burst phases of nearby phones. None of that work is "fast" in the way marketing pages count cycles, it's dispatch-heavy, allocation-heavy, parser-heavy. And the single BLE radio has to time-slice between scanning and holding the phone connection at the same time.
If the chip can't keep up, advertisements drop inside the firmware queue and never reach the aggregator. That's the failure mode we're optimizing against. Everything below comes back to that.
Cores: the only one that actually matters
| ESP32-S3 | ESP32-C5 | |
|---|---|---|
| Architecture | Xtensa LX7, dual-core | RISC-V, single-core |
| Clock | 240 MHz | 240 MHz |
This is the headline. AirLeak splits its work across the two cores:
- Core 0: the NimBLE host and the scan callback. Lives inside the Espressif radio stack's interrupt + task context. Also drives the peripheral advertising, the GATT server, and the BLE delta-stream notify task. Cannot block on heavy parsing.
- Core 1: parser + aggregator + classifier. Pulls from the raw-advertisement ring, does all the expensive decode work, never touches the radio.
This split is the only way we keep up without dropping advertisements under a dense load while also holding a phone connection and streaming to it. The single radio already has to time-slice between scanning and the connection; the compute can't be allowed to contend with the radio task too.
Now collapse those two cores onto one. The single core has to do RX work, parsing, classification, and the GATT/notify output, plus ride the BLE controller's housekeeping interrupts. With everything on one core, under a burst the core pegs, the radio task starts missing its scheduling deadline, and the BLE controller drops advertisements before they ever reach our handler. We only know they were dropped because the controller exposes a counter, they're invisible upstream.
The C5 isn't "slower than the S3" in raw clock terms. They're both 240 MHz. The C5 is slower for this workload because it has half the parallel dispatch capacity, and the workload is dispatch-bound.
For a chip whose only job is "decode and stream every nearby radio packet without ever dropping," that's disqualifying.
RAM: where the marketing stops mentioning it
| ESP32-S3 | ESP32-C5 | |
|---|---|---|
| Internal SRAM | 512 KB | 320 KB |
| External PSRAM (max) | 8 MB octal SPI | 2 MB quad SPI |
| PSRAM bus width | 8-bit (octal) | 4-bit (quad) |
| PSRAM bandwidth | ~80 MB/s | ~20 MB/s |
Three things follow from this:
-
Aggregator state is large. AirLeak holds a per-device record for every MAC seen, with service UUIDs, RSSI history and EMA, parsed Apple Continuity sub-message slots, Find My pubkey fragments, AirDrop hash prefixes, and the alert ring. The aggregator is a 768-record table plus the delta ring and alert ring, all PSRAM-backed. We need PSRAM, and the C5's smaller cap is tighter than we want for the working set.
-
PSRAM bandwidth is real. Octal vs. quad SPI is a 4× bandwidth difference. Every record touch, copy, and serialize that lands in PSRAM costs proportionally more on the C5, on a chip that already had no compute headroom. This is the kind of cost that doesn't show up on any spec sheet.
-
Internal SRAM matters for the hot path. The raw-advertisement ring, the BLE callback's local buffers, and the parser scratch space all live in internal SRAM to avoid PSRAM round-trips. 512 KB vs. 320 KB is the difference between fitting comfortably and constantly tuning ring sizes to avoid spilling, and a low-internal-heap condition is exactly what trips AirLeak's safe mode.
USB and the shared product line
| ESP32-S3 | ESP32-C5 | |
|---|---|---|
| USB | OTG full-speed (12 Mbps) | USB-Serial-JTAG only |
| HID class capability | Yes | No |
AirLeak streams to the phone over BLE, not USB, so raw USB throughput isn't on its hot path. But the S3's proper USB OTG controller matters for the product line: it speaks HID, MSC, and composite class combinations, which is what lets the same hardware platform run the ZeroTrace HID / Kit firmware. The C5's USB-Serial-JTAG has no HID-class advertising, so it can't be reused that way, it would lock the line to separate chips for separate firmware variants. Standardizing on the S3 keeps one board family across AirLeak and the HID firmware. (The S3's USB OTG also gives us a clean USB-serial path for the optional AL_DEBUG_SERIAL development diagnostics.)
Radio: what we'd give up, and what it actually costs us
The C5's radio is genuinely more capable on paper:
- 5 GHz Wi-Fi 6 (the S3 only does 2.4 GHz).
- BT 5.2 (the S3 is BT 5.0).
- Slightly better idle current.
These are real. But AirLeak is a BLE-only device:
Wi-Fi capability, including 5 GHz:
Irrelevant. AirLeak doesn't capture Wi-Fi at all, the firmware runs the radio in BLE-only mode. All BLE traffic, every AirTag, AirPods, watch, phone, smart-home device, lives on 2.4 GHz, which both chips cover. There is zero AirLeak-visible benefit to the C5's 5 GHz Wi-Fi.
BT 5.2 vs 5.0:
The 5.2 deltas that matter to AirLeak are mostly nothing. AirLeak is a passive observer plus a single GATT link; it doesn't use Isochronous Channels, EATT, or Periodic Advertising sync, which all require active participation. The S3's BT 5.0 (with the 2M PHY we enable for the capture-stream link) covers what we need.
Idle current:
Real but irrelevant. AirLeak is powered over USB-C. There is no battery to optimize for.
Stack maturity: the cost no one budgets for
The ESP32-S3 has been shipping in volume since 2021. The ESP-IDF BLE controller (NimBLE), USB OTG stack, FreeRTOS port, PSRAM cache controller, all of it has gone through four years of production hardening. We hit two BLE-controller bugs during AirLeak's development; both already had documented workarounds in the IDF issue tracker.
The C5 entered production in late 2024. Its IDF support is still being stabilized, with community reports of stack regressions on early IDF releases. For a tool whose entire value depends on never silently dropping advertisements, building on a stack that's still settling is a meaningful risk.
This isn't an attack on Espressif's engineering, every new chip goes through this. It's just that "shipping a stable product today" and "building on the newest silicon" are competing goals.
The trade-off in one table
| Dimension | S3 | C5 | Winner for AirLeak |
|---|---|---|---|
| CPU dispatch capacity | 2 cores @ 240 MHz | 1 core @ 240 MHz | S3 |
| Internal SRAM | 512 KB | 320 KB | S3 |
| PSRAM cap | 8 MB octal | 2 MB quad | S3 |
| PSRAM bandwidth | ~80 MB/s | ~20 MB/s | S3 |
| USB peripheral | OTG, full-class | Serial-JTAG only | S3 (shared product line) |
| Wi-Fi bands | 2.4 only | 2.4 + 5 | C5 (irrelevant, AirLeak is BLE-only) |
| BT version | 5.0 | 5.2 | C5 (irrelevant to passive scanner) |
| Idle current | higher | lower | C5 (irrelevant on USB power) |
| Stack maturity | 4+ years | <1 year | S3 |
The dimensions where the C5 wins are the ones AirLeak doesn't depend on. The dimensions where the S3 wins are exactly the ones that bound AirLeak's throughput.
What would change the answer
A future ZeroTrace product with a different workload could absolutely use the C5 (or whatever Espressif ships next) over the S3:
- Battery-powered sniffer with strict idle budget, C5 wins.
- A Wi-Fi capture tool that needs 5 GHz, needs the C5's radio.
- Active participation in modern Wi-Fi 6 / BT 5.2 features, needs the newer stack.
AirLeak isn't any of those. It's a passive, plugged-in, dispatch-bound, BLE-only scanner. For that workload the S3 is the right chip, and the chip-comparison websites won't tell you that because their model is "newer = better" with no reference to what you're actually doing with the silicon.
We didn't pick the S3 because it's "the best ESP32." We picked it because for AirLeak's specific dispatch-bound, BLE-only, scan-while-connected workload, it's the only ESP32 that doesn't bottleneck. The C5's marketing wins are wins on dimensions AirLeak doesn't measure.