$2 Ad Blocker: ESP32-C3 Sinks 140'000 Domains in Flash
Most ESP32 DNS sinkholes load the blocklist into RAM, which means you need a board with PSRAM, around $8. This project does something smarter: it stores domains as sorted 40-bit hashes in flash memory and binary-searches them. The result is 140'000+ blocked domains on a $2 ESP32-C3 with no PSRAM, 50 KB of RAM, and 10 ms lookups [1].
The trick is that you don't need the full domain string in memory. A 40-bit FNV-1a hash is enough to identify a domain with negligible collision risk. At 141'000 domains, you get zero collisions. At 537'000, you get about one. The hashes are sorted and stored in flash, so lookup is a binary search with roughly 18 flash reads, including WiFi round-trip time [1].
Here is how it compares to the string-in-RAM approach:
String in RAM: ~2.5 MB of RAM for 141k domains. Requires PSRAM. ESP32 + PSRAM costs ~$8.
Hash in flash: 0.67 MB of flash for 141k domains. 50 KB of RAM. ESP32-C3 costs ~$2 [1].
The same trick scales up. On a 16 MB ESP32-S3, hash-in-flash holds about 2.7 million domains versus 466k for strings in 8 MB of PSRAM. Hashes in flash beat strings in PSRAM basically everywhere, the C3 just makes it undeniable [1].
The project supports standard hosts files, plain domain lists, and AdGuard/Adblock basic rules. It has a web dashboard, OTA updates for both firmware and blocklist, a captive portal for WiFi setup, and a printable enclosure. You can plug it directly into your router's USB port and forget about it [1].
It was featured on Tom's Hardware, XDA Developers, and Korben. The full project is on GitHub under MIT license, built with PlatformIO [1][2].
Hardware ad blocking at the DNS level is not new, Pi-hole has been doing it for years on a Raspberry Pi. But fitting it on a $2 chip with 50 KB of RAM, that is a genuinely elegant engineering trick. The 40-bit hash insight is the kind of thing that seems obvious in hindsight but nobody actually did until now.
Sources:
[1] ESP32-C3 Adblock on GitHub
[2] Tom's Hardware coverage