Files
wdmUI/decisions/0003-mqtt-como-espina-dorsal.md

2.5 KiB

ADR-0003 · MQTT as the spine of the system

Status: accepted Date: 2026-05

Context

The platform has many independent processes that need to communicate: cameras → Frigate → enrichers → forensic engine → console → hub. Options considered:

  • REST APIs everywhere: tight coupling, polling overhead, hard to add subscribers.
  • gRPC streams: better but still point-to-point, no topic-based filtering.
  • Kafka: too heavy for edge devices, requires Zookeeper or KRaft, persistent disk-heavy.
  • NATS: lightweight but newer, less ecosystem maturity.
  • MQTT: mature, lightweight, broker available everywhere (Mosquitto), topic-based, retain messages, QoS levels, well-known TLS bridge mechanics.

Decision

MQTT is the spine of the system. Mosquitto runs on the router as the local broker. Bridges to the hub are configured selectively, with topic remapping. Components communicate via MQTT topics with a documented contract (see docs/01-architecture/mqtt-contract.md).

Key topics:

hai/<cam_id>/events/<type>      # detection events
hai/<cam_id>/state/<key>        # retained state (online, fps)
hai/<cam_id>/snapshots/<n>      # frame snapshots — NEVER bridged
hai/<cam_id>/telemetry/<key>    # raw telemetry — NEVER bridged
hai/_registry/announce          # service discovery
hai/_registry/heartbeat/<id>    # liveness
hai/healthd/health              # selftest reports
hai/_bridge/status              # bridge health (retained)
_cmd/<command>                  # commands incoming from hub

Sovereignty principle: snapshots and raw telemetry never bridge. Aggregated health does. Events do (with site prefix). The bridge.conf policy is in GitOps and visible in the UI.

Consequences

Good:

  • Adding a new subscriber is free (no config changes upstream).
  • Selective bridging gives operational sovereignty as a programmable property.
  • mosquitto_sub is a superb debugging tool always available.
  • Retained messages handle late-joining subscribers correctly.

Bad / trade-offs:

  • MQTT 5 has features we want (response topics, message expiry) but Mosquitto's MQTT5 support is partial — we stay on MQTT 3.1.1 for compatibility.
  • No native request-response semantics — we use req-id correlation in payloads where needed.
  • Encryption at rest of the broker DB is not transparent — addressed via LUKS at the OS layer.

Alternatives considered

See above. Kafka was the strongest alternative; rejected primarily for edge-device cost and operational complexity.