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 bus throughput, 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 Wi-Fi management frame and BLE advertisement in the air.
- Decode each one (parse Information Elements, vendor-specific blobs, Apple Continuity, MS FMD, Find My, Eddystone, Fast Pair, Tile, Samsung SmartTag, FMDN, Microsoft Swift Pair).
- Aggregate into a per-device state machine, run classification + leak heuristics.
- Stream every event up over USB CDC at 921600 baud to the desktop, which pushes through the JS bridge into React state in real time.
In a moderately busy room (think coffee shop, office, transit hub) that's 600–2000 events/sec sustained, with bursts to 5k+/sec during 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. The radio is asleep for >95% of the time. The CPU and the USB bus are not.
If the chip can't keep up, events drop silently inside the firmware queue and never reach the desktop. 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 runs two pinned tasks:
- Core 0: BLE/Wi-Fi RX callbacks. Lives inside the Espressif radio stack's interrupt + task context. Cannot block, cannot allocate from the heap aggressively, cannot do parsing.
- Core 1: Aggregator + parser + classifier + USB writer. Pulls from the lock-free SPSC ring, does all the expensive work, never touches the radio.
This split is the only way we hit the throughput target without dropping. Measured on the S3:
- Steady-state ~1500 events/sec → core 0 ~28% load, core 1 ~42% load. Plenty of headroom.
- 5k/sec burst → core 0 ~60%, core 1 ~85%. Still no drops.
Now collapse those two cores onto one. The single core has to do RX work, parsing, classification, and USB output, plus ride the BLE controller's housekeeping interrupts. Bench numbers from a C5 dev board running the same parser pipeline (single-core obviously):
- Steady ~1500 events/sec → core ~92% load. Already dangerously close to saturation.
- 5k/sec burst → core pegs at 100%, the radio task starts missing its scheduling deadline, BLE controller drops advertisements before they ever reach our handler. We only know events were dropped because the controller exposes a counter — they're invisible to the desktop.
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 in the session — service UUIDs, probed SSIDs ring, RSSI history, parsed Apple Continuity sub-message slots, Find My pubkey fragments, vendor IEs, MS FMD frames. After ~30 minutes in a busy environment that's 2–4 MB of live state. We need PSRAM. The C5's 2 MB cap means we'd start evicting devices mid-session.
-
PSRAM bandwidth is real. Octal vs. quad SPI is a 4× bandwidth difference. A struct copy from PSRAM into the SPSC ring on the S3 takes ~10 µs for a typical event payload; on the C5 the same copy takes ~40 µs. Multiply by 1500/sec and you've eaten 60 ms/sec of CPU time on memcpy alone — on a chip that already had no headroom. This is the kind of cost that doesn't show up on any spec sheet.
-
Internal SRAM matters for the hot path. The SPSC ring, the BLE callback's local buffers, 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.
USB: the C5's biggest regression
| ESP32-S3 | ESP32-C5 | |
|---|---|---|
| USB | OTG full-speed (12 Mbps) | USB-Serial-JTAG only |
| Effective CDC throughput | ~1 MB/s sustained | ~700 KB/s, with stalls |
| HID class capability | Yes | No |
The S3 has a proper USB OTG controller. It speaks CDC (what we use for the desktop link), HID (used by ZeroTrace Kit firmware), MSC, and composite class combinations. The host driver path is a normal USB stack on both ends.
The C5 has USB-Serial-JTAG. It looks like USB to the host, but it's a much narrower implementation:
- Fixed CDC interface, no class swapping.
- Lower max throughput, and our measurements show periodic millisecond-scale stalls when the JTAG side of the peripheral wakes up.
- No HID-class advertising, which means the same hardware can't be reused as a Kit-style device later. Locks the product line to two separate chips for two firmware variants.
For AirLeak specifically: at 1500 events/sec each averaging ~120 bytes JSON, we're pushing ~180 KB/s steady. That's well within S3's headroom. On the C5's USB-Serial-JTAG, the periodic stalls cause back-pressure into the SPSC ring, which then has to absorb the lull or drop. With one core already pegged on parsing, those drops will happen.
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 for AirLeak's job:
5 GHz blindness, audited honestly:
- All BLE traffic — every AirTag, AirPods, watch, smart-home device — is on 2.4 GHz. Zero loss.
- Most modern APs are dual-band. The 2.4 GHz beacon advertises the same SSID, security mode, channel-utilization stats, and station count as the 5 GHz radio. The only thing we miss is the 5 GHz radio's separate BSSID, which matters for pinpointing a specific physical AP but not for "is this a corporate / hotel / home network with X devices on it."
- Phone probe-requests almost always go out on 2.4 GHz first — that's the lowest-common-denominator band that every old AP supports. Modern phones add 5 GHz probes, but the 2.4 GHz copy still goes out, so we still see the SSID.
- Devices that are only on 5 GHz are rare in the wild — mostly enterprise gear with 2.4 GHz administratively disabled. AirLeak's target environments (cafés, transit, residential) very rarely fit that profile.
Net effect: ~5–8% of Wi-Fi-only observations would be richer with a 5 GHz radio. Zero impact on BLE, which is the bulk of what AirLeak surfaces.
BT 5.2 vs 5.0:
The 5.2 deltas that matter to a passive scanner are mostly nothing. LE Power Control could theoretically help with distance estimation, but it's only useful for connected links; AirLeak is purely a passive listener. Isochronous Channels, EATT, Periodic Advertising sync — all require active participation. We don't participate.
Idle current:
Real but irrelevant. AirLeak is plugged in over USB. 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, Wi-Fi sniffer mode, USB CDC 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. The IDF BLE/Wi-Fi support is still being stabilized. Multiple long-standing community reports of stack regressions on early IDF releases. For a tool whose entire value depends on never silently dropping data, 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 |
| Wi-Fi bands | 2.4 only | 2.4 + 5 | C5 (small real-world delta) |
| 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.
- 5 GHz-only environment like an enterprise audit tool that needs 5 GHz BSSID resolution — 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, 2.4 GHz-dominant 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, USB-streaming, 2.4 GHz workload, it's the only ESP32 that doesn't bottleneck. The C5's marketing wins are wins on dimensions AirLeak doesn't measure.