ADR-004: Offline-First ESP32 Architecture¶
Status: Accepted Date: 2026-02-25
Context¶
The ESP32 controller at the door must make access decisions reliably. WiFi connectivity at the hackerspace can be intermittent — the router may reboot, the ISP may have outages, or the backend server may be down for maintenance. The door must continue to function.
Additionally, the ESP32 has a single radio shared between WiFi and BLE. It cannot use both simultaneously, and it needs BLE for controlling the NUKI Smart Lock Ultra.
Options Considered¶
A) Online-First (query backend for each access decision)¶
- Pro: Always up-to-date access decisions
- Pro: No local storage needed
- Con: Door is unusable when WiFi or backend is down
- Con: Added latency for each card scan (WiFi connect + HTTP request + WiFi disconnect)
- Con: WiFi/BLE radio contention — NUKI commands blocked during HTTP requests
B) Hybrid (local cache + real-time verification when possible)¶
- Pro: Works offline, benefits from online when available
- Con: Complex logic to decide when to go online
- Con: Higher WiFi usage, more BLE/WiFi switching
C) Offline-First (periodic sync of signed allow-list)¶
- Pro: All decisions are local and fast (<10ms)
- Pro: Works without any network connectivity
- Pro: Predictable WiFi usage pattern (every 5 minutes)
- Pro: BLE always available for NUKI control except during sync windows
- Con: Up to 5 minutes of staleness after a key is revoked
- Con: Cannot enforce real-time rules without going online
Decision¶
Offline-First (Option C) with a Conditional exception for access types that explicitly require online approval.
The ESP32 stores a signed allow-list in LittleFS flash and loads it into RAM on boot. Every 5 minutes, it connects to WiFi, fetches updates, and disconnects. Between syncs, all access decisions use the cached list.
The one exception is ACCESS_CONDITIONAL, where the entry explicitly requires real-time backend approval (e.g., a backup keyholder who needs an organizer's confirmation). In this case, the ESP32 connects to WiFi on-demand for a single HTTP request.
Network Connectivity¶
Although the ESP32 works offline for access decisions, it requires periodic network access for allow-list sync, event reporting, and time synchronization. The default transport is WiFi, but wired Ethernet is strongly recommended for production (exterior/main doors) for reliability. ESP32 boards with built-in Ethernet (e.g., WT32-ETH01, Olimex ESP32-POE) eliminate WiFi dependency entirely and avoid the WiFi/BLE radio contention described below.
WiFi is acceptable for:
- Development and testing — simpler setup, no extra hardware
- Non-critical doors — interior doors where brief connectivity loss is tolerable
For production with Ethernet, the BLE time-division concern disappears for sync operations — Ethernet runs independently of the radio, so BLE remains available at all times. The WiFi/BLE switching described below only applies to WiFi-based deployments.
WiFi/BLE Time-Division¶
Normal operation (5 min cycle):
├── 0:00 - 4:55 BLE active (NUKI control available, NFC scanning active)
├── 4:55 - 5:00 WiFi active (sync allow-list, report events, heartbeat)
└── repeat
On CONDITIONAL card scan:
├── WiFi on (POST approval request)
├── Wait up to 60 seconds for response
├── WiFi off, BLE on
└── If approved: unlock NUKI via BLE
Allow-List Validity¶
- Monotonic version: ESP32 rejects lists with
version <= current_version - Validity window:
valid_untilisgenerated_at + 24 hoursby default - Staleness handling: If
valid_untilhas passed and no sync is possible, UNRESTRICTED and EMERGENCY entries still work. SCHEDULED entries are denied (cannot reliably evaluate time rules with potentially incorrect local time).
Consequences¶
- Card scan to door unlock is fast (~50ms: Wiegand decode + UID lookup + BLE command)
- Key revocation takes effect within 5 minutes (next sync)
- ESP32 needs ~10KB of flash for the allow-list (sufficient for 200 entries)
- LittleFS partition (192KB) stores the allow-list file persistently
- The backend must be reachable at least once every 24 hours for SCHEDULED entries to remain valid
- CONDITIONAL access requires WiFi at the moment of card scan