SpectraIO — Industrial Vibration Observability
A condition-monitoring platform for rotating equipment: battery-powered wireless vibration sensors on the machine, an IIoT gateway with its own cellular uplink, and a self-hosted pipeline that turns every reading into a stored spectrum, a trend, and — when a threshold is crossed — an alert on somebody's phone.
Running in production today on a live fleet at an operating cement plant — crushers, vane compressors, gearboxes and motors — streaming over 4G, and serving two organizations from a single codebase.
The Problem
Vibration analysis is how you catch a failing bearing weeks before it seizes. Doing it properly has traditionally meant one of two things: a technician walking the plant with a handheld collector on a monthly route, or a six-figure enterprise platform wired into the plant network.
The first misses anything that develops between routes. The second was not available here, for a reason that has nothing to do with budget: the plant network is off limits. Nothing plugs into it, and no inbound port is opened anywhere — not at the plant, not at the platform.
That single constraint rules out most of the market.
The Constraints That Defined the Design
| Constraint | Consequence |
|---|---|
| The link is cellular, metered, and shared by the whole site | Every byte is a design decision. A full reading costs about 1 MB, so it has to be worth sending |
| The plant network is off limits | No inbound ports anywhere. Nothing plugs into OT |
| An analyst needs resolution, not a pretty chart | ~31 CPM at the frequencies where bearing faults live, with every stored point rendered |
| The site is unattended | An outage nobody is notified about is an outage that lasts 19 hours — measured, not hypothetical |
The Solution
- Edge: CTC wireless vibration sensors → Access360 gateway → HiveMQ over MQTT 5.0, on a cellular uplink independent of the plant network
- Ingestion: a purpose-built multi-gateway ingester microservice writing into InfluxDB 3 Enterprise, queried over Flight SQL
- Application: Next.js and TypeScript with Apache ECharts on Canvas, rendering 4,000 stored FFT bins per axis
- Exposure: Cloudflare Tunnel — no port forwarding, no public IP, and the data plane stays entirely private
- Analysis: bearing fault-frequency markers (BPFO, BPFI, BSF, FTF), a harmonic ruler, band zoom and per-axis statistics
Multi-Tenant From the Start
One codebase serves two organizations, with white-labelled instances carrying each customer's own branding. Tenant separation, per-tenant thresholds and role separation are part of the data model rather than a deployment trick — which is what makes adding the third organization a configuration change instead of a fork.
Engineering Decisions Worth Naming
Server-side downsampling. Frontend payloads are held to roughly 2,000 points per request. On a metered cellular link shared with the plant's own traffic, the query engine does the reduction, not the browser.
SQL over Flux. InfluxDB 3 is queried via Flight SQL exclusively. Committing to one query path kept the data layer legible as the schema grew.
Alerting is part of the product, not an add-on. The 19-hour outage in the table above is a real measurement from an early deployment. An unattended site with no alerting is not monitored — it is merely instrumented.
Stack
- Frontend: Next.js, TypeScript, Apache ECharts
- Data: InfluxDB 3 Enterprise, Flight SQL
- Messaging: HiveMQ, MQTT 5.0
- Edge: CTC dynamic sensors, Access360 gateway, cellular router
- Platform: Docker for beta, K3s for production, Cloudflare Tunnel
- Observability: Grafana, structured logs, query latency and error metrics
Links
- Engineering write-up — the decisions, the numbers, and the two outages that shaped the design
- Product brief — the commercial overview, English and Spanish
The application source is private. Live demo on request.