Real-time vibration analysis for rotating equipment means processing accelerometer readings continuously—computing RMS, peak values, and trend deviations—and triggering maintenance alerts before a bearing fails or a shaft goes out of balance. RisingWave, a PostgreSQL-compatible streaming database, handles this with streaming SQL and no specialized signal processing platform.
Why Vibration Analysis Needs Real-Time Processing
Rotating equipment—motors, pumps, compressors, fans, gearboxes—is the backbone of industrial operations. When a bearing fails or a rotor becomes unbalanced, the first indicators appear in the vibration signature hours or days before the failure becomes audible or visible.
Traditional condition monitoring systems poll vibration sensors at low frequency—every few seconds or minutes—and store raw samples in a historian. Trend analysis is done manually by reliability engineers reviewing weekly reports. This approach catches large, fast-developing faults but misses the slow degradation patterns that precede most mechanical failures.
Streaming vibration analysis changes the economics. Every accelerometer sample flows through a continuous SQL pipeline. RMS values, peak-to-peak amplitudes, and crest factors are computed in real time. When a metric crosses a threshold or shows an unusual trend, an alert fires immediately—not at the next scheduled report.
How Streaming SQL Solves This
Vibration data from wireless or wired accelerometers is published to Kafka via edge gateways. RisingWave ingests this stream and maintains materialized views for:
- RMS and peak amplitude per machine, updated every tumble window
- Trend tracking comparing current window to baseline
- Fault indicators based on ISO 10816 vibration severity thresholds
- Alert sinks delivering maintenance notifications to work order systems
Step-by-Step Tutorial
Step 1: Connect Your Data Source
CREATE SOURCE vibration_samples (
machine_id VARCHAR,
sensor_id VARCHAR,
axis VARCHAR, -- 'X', 'Y', 'Z', 'overall'
acceleration DOUBLE, -- mm/s² or g
velocity_rms DOUBLE, -- mm/s RMS
temperature DOUBLE, -- bearing temperature °C
rpm DOUBLE, -- rotation speed
event_time TIMESTAMPTZ
) WITH (
connector = 'kafka',
topic = 'vibration-data',
properties.bootstrap.server = 'kafka:9092',
scan.startup.mode = 'earliest'
) FORMAT PLAIN ENCODE JSON;
Also connect to the machine asset registry:
CREATE SOURCE machine_registry (
machine_id VARCHAR,
machine_name VARCHAR,
machine_class VARCHAR, -- 'pump', 'motor', 'compressor', 'fan'
iso_class VARCHAR, -- ISO 10816 class: I, II, III, IV
rated_rpm DOUBLE,
location VARCHAR,
criticality VARCHAR -- 'critical', 'important', 'general'
) WITH (
connector = 'postgres-cdc',
hostname = 'cmms-db.plant',
port = '5432',
username = 'rw_reader',
password = 'secret',
database.name = 'cmms',
schema.name = 'public',
table.name = 'machine_registry'
);
Step 2: Build the Real-Time View
Track the current vibration state per machine with the latest readings:
CREATE MATERIALIZED VIEW machine_vibration_state AS
SELECT DISTINCT ON (machine_id, sensor_id, axis)
v.machine_id,
m.machine_name,
m.location,
m.criticality,
m.iso_class,
v.sensor_id,
v.axis,
v.velocity_rms,
v.acceleration,
v.temperature,
v.rpm,
v.event_time AS last_updated
FROM vibration_samples v
JOIN machine_registry m USING (machine_id)
ORDER BY machine_id, sensor_id, axis, event_time DESC;
Step 3: Window-Based Aggregations
Compute 10-minute vibration statistics per machine and axis—the foundation for ISO 10816 severity classification:
CREATE MATERIALIZED VIEW vibration_stats_10min AS
SELECT
machine_id,
sensor_id,
axis,
window_start,
window_end,
AVG(velocity_rms) AS avg_velocity_rms,
MAX(velocity_rms) AS peak_velocity_rms,
SQRT(AVG(acceleration * acceleration)) AS rms_acceleration,
MAX(acceleration) AS peak_acceleration,
MAX(acceleration) / NULLIF(
SQRT(AVG(acceleration * acceleration)), 0
) AS crest_factor,
AVG(temperature) AS avg_bearing_temp,
AVG(rpm) AS avg_rpm,
COUNT(*) AS sample_count
FROM TUMBLE(vibration_samples, event_time, INTERVAL '10 MINUTES')
GROUP BY machine_id, sensor_id, axis, window_start, window_end;
Track trending: compare current window against a 1-hour baseline to detect rising vibration:
CREATE MATERIALIZED VIEW vibration_trend_1hr AS
SELECT
machine_id,
sensor_id,
axis,
window_start,
window_end,
AVG(velocity_rms) AS avg_rms,
STDDEV(velocity_rms) AS stddev_rms,
MAX(velocity_rms) - MIN(velocity_rms) AS rms_range
FROM TUMBLE(vibration_samples, event_time, INTERVAL '1 HOUR')
GROUP BY machine_id, sensor_id, axis, window_start, window_end;
Step 4: Alerts and Sinks
Apply ISO 10816-based severity thresholds. For Class II machines (medium motors), warning is > 4.5 mm/s RMS and fault is > 11.2 mm/s RMS:
CREATE MATERIALIZED VIEW vibration_alerts AS
SELECT
s.machine_id,
r.machine_name,
r.location,
r.criticality,
r.iso_class,
s.sensor_id,
s.axis,
s.avg_velocity_rms,
s.peak_velocity_rms,
s.crest_factor,
s.avg_bearing_temp,
s.window_end AS alert_time,
CASE
WHEN s.avg_velocity_rms > 11.2 THEN 'FAULT'
WHEN s.avg_velocity_rms > 4.5 THEN 'WARNING'
WHEN s.avg_bearing_temp > 85 THEN 'BEARING_HOT'
WHEN s.crest_factor > 6.0 THEN 'BEARING_WEAR'
END AS severity,
CASE
WHEN s.avg_velocity_rms > 11.2 THEN 'Vibration exceeds ISO 10816 fault threshold'
WHEN s.avg_velocity_rms > 4.5 THEN 'Vibration exceeds ISO 10816 warning threshold'
WHEN s.avg_bearing_temp > 85 THEN 'Bearing temperature critical'
WHEN s.crest_factor > 6.0 THEN 'High crest factor indicates bearing defect'
END AS diagnosis
FROM vibration_stats_10min s
JOIN machine_registry r USING (machine_id)
WHERE s.avg_velocity_rms > 4.5
OR s.avg_bearing_temp > 85
OR s.crest_factor > 6.0;
CREATE SINK vibration_alerts_sink
FROM vibration_alerts
WITH (
connector = 'kafka',
topic = 'maintenance-alerts',
properties.bootstrap.server = 'kafka:9092'
) FORMAT PLAIN ENCODE JSON;
Comparison Table
| Manual Walkdown | Scheduled CMS Reports | Streaming SQL (RisingWave) | |
| Detection latency | Days to weeks | Hours to days | Sub-second |
| Coverage | Sampled assets | Monitored assets | All connected assets |
| ISO threshold enforcement | Manual comparison | Batch check | Continuous SQL WHERE |
| Work order creation | Manual | Semi-automated | Automated via sink |
| Trending | Monthly charts | Weekly reports | Continuous |
FAQ
Does RisingWave handle the high sample rates of vibration sensors?
Industrial vibration sensors typically publish aggregated metrics (RMS, peak) at 1-10 Hz rather than raw 10 kHz waveforms. If raw waveforms are required for FFT analysis, pre-process them at the edge gateway and publish only frequency-domain features to Kafka. RisingWave handles the aggregated metrics stream efficiently.
How do I account for variable speed machinery in ISO thresholds?
Add speed-band logic to your alerts view using CASE expressions on avg_rpm. ISO 10816 velocity limits vary with machine speed; define threshold lookup tables in RisingWave CREATE TABLE and join them in your alert materialized view.
Can I correlate vibration with process conditions?
Yes. Join vibration_stats_10min with a process conditions source (from SCADA or a separate Kafka topic) on machine_id and overlapping time windows. This enables correlation between high load, high temperature, and elevated vibration—essential for root cause analysis.
Key Takeaways
- Streaming vibration analysis in RisingWave computes RMS, peak amplitude, and crest factor continuously using tumble window aggregations—detecting bearing wear and imbalance before failure.
- ISO 10816 severity thresholds are enforced as SQL WHERE conditions in a materialized view that auto-updates as new windows close.
- Maintenance alerts sink to Kafka and can trigger work orders in CMMS systems with millisecond latency.
- The approach scales across an entire fleet—hundreds of rotating machines—without additional infrastructure.

