/

Developer Guide

Sensor Service Architecture

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.


Architectural Style

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| BR

The 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.


Key Architectural Decisions


Integration

For the request lifecycle, the module base-class template, the extension guide, and the API, see the Sensor Service internals page.