/

CrowdVision · source-available, not open source · © 2026 Nicolò Ghignatti

Telemetry Service Architecture

Bounded context: Telemetry Ingestion · Stack: Rust / Axum / Postgres + TimescaleDB · Code-level walkthrough: Telemetry Service

The telemetry realises the Telemetry Ingestion context. It is the platform’s ingestion gateway, and its architecture answers two independent pressures: absorbing new sensor types without touching the core, and keeping every I/O technology out of the logic that decides what a reading means.


Architectural Style

Hexagonal (ports & adapters) and microkernel on orthogonal axes. They are not competing patterns here; each governs a different direction of change.

AxisPatternVaries
Outward — infrastructurePorts & adaptersPostgres, Redis, Kafka, digital-twin, physical devices
Inward — domainMicrokernelwhich metrics exist, what they validate, which bounds they carry

The Node predecessor had the microkernel half only. Its modules owned their own persistence and Redis calls, so infrastructure reached into every metric implementation.

Layers

DirectoryHoldsMay import
src/types/pure types, SensorPlugin and ActionSpec, threshold and query rulesnothing
src/kernel/use cases over Arc<dyn Port> — the microkernelcontracts
src/plugins/one file per metric, each a SensorPlugincontracts
src/adapters/Postgres, Redis, Kafka, HTTP in and outeverything

The kernel never names a plugin. Every metric-specific decision is reached through a &dyn SensorPlugin resolved from PluginRegistry, so a new metric is a new file plus one registration line in main.rs.

tests/architecture.rs enforces the table: no crate::plugins or crate::adapters under src/kernel, no I/O crate under src/kernel or src/types, and no plugin importing a sibling.

graph TD
    subgraph Driving
        HTTP[HTTP API]
        KC[Kafka registration consumer]
    end
    subgraph Kernel
        K[Use cases: ingest, readings, thresholds, sensors, actions, registration]
        R[PluginRegistry]
    end
    subgraph Plugins
        T[temperature]
        P[peopleCount]
        A[airQuality]
    end
    subgraph Driven
        PG[(Postgres + Timescale)]
        RD{{Redis pub/sub}}
        KP[Kafka producer]
        TW[digital-twin directory]
        DEV[Device ACL]
    end
    HTTP --> K
    KC --> K
    K --> R
    R --> T
    R --> P
    R --> A
    K --> PG
    K --> RD
    K --> KP
    K --> DEV
    HTTP -.->|authz| TW

Components & Connectors diagram

Telemetry Service C&C diagram

Key Architectural Decisions


Integration

For the request lifecycle, the plugin template, the extension guide, and the API, see the Telemetry Service internals page.