Developer Guide
Bounded context: Telemetry Ingestion · Stack: Node.js / Express · Code-level walkthrough: Sensor Service
The sensor-service realises the Telemetry Ingestion context. It is the platform’s ingestion gateway, and its architecture is shaped by two pressures: accepting readings from constrained hardware without making it wait, and absorbing new sensor types without rewriting the core.
A microkernel with Strategy modules, layered on a fast-path / slow-path execution model. Generic controllers hand off to a kernel that resolves the module owning the incoming metric type; each module implements ISensorModule and owns its own validation, persistence, and side effects — the kernel never branches on sensor type itself, so a new metric is a new module registered at startup, not a change to existing code.
ISensorModule’s contract enforces the fast-path/slow-path split at the type level, not just by convention: validate() must be pure and synchronous, and process() is documented to run only after the HTTP 202 has already been flushed, in a fire-and-forget context that must not assume the connection is still alive. A constrained sensor gets an immediate answer; persistence and downstream publishing happen after the response is already gone.
graph TD
subgraph Router
R[router.ts]
end
subgraph Controller
CTRL[Generic Controllers]
end
subgraph Kernel
K[Sensor Kernel]
end
subgraph "Strategy Modules — implement ISensorModule"
T[Temperature Module]
P[People Count Module]
A[Air Quality Module]
F[Future Modules...]
end
subgraph Service
SVC[Module Services]
end
R --> CTRL
CTRL -->|"validate() — sync, fast path"| K
K --> T
K --> P
K --> A
K --> F
T -->|"process() — after 202, slow path"| SVC
P --> SVC
A --> SVC
SVC -.-> DB[(sensor-db)]
SVC -.->|publish, every module| BR{{"broker"}}
T -.->|publish: alerts:temperature| BRThe temperature module publishes to a plain Redis channel (alerts:temperature); it holds no reference to notification-service and has no idea whether anything is subscribed. That decoupling is what makes the module addable and removable without touching another service.
sensor-db; no other service reads it.alerts:temperature channel — with no reference to whichever service ends up consuming either one. Receives a threshold baseline from twin-service, and exposes a self-describing metric catalog to contracts-service — see Communication & Data Flow.For the request lifecycle, the module base-class template, the extension guide, and the API, see the Sensor Service internals page.