- Cloud-only PHM for 100 sensors at 10kHz costs $18,240/year (AWS), dominated by $936/month data transfer fees.
- Edge preprocessing with Raspberry Pi clusters cuts recurring costs to $444/year, but adds maintenance burden and limits algorithm iteration.
- Hybrid architecture (edge FFT + selective cloud upload) balances cost ($2,292/year) and flexibility, uploading raw data only on anomaly triggers.
- At 500+ sensors, cloud TCO becomes competitive once DevOps personnel costs are included—edge scales poorly beyond small deployments.
- Latency matters for safety-critical systems (<100ms), but bearing fault detection tolerates 500-2000ms cloud round-trip delays.
The $800/Month AWS Bill That Made Me Rethink Everything
Streaming raw vibration data from 100 sensors to AWS at 10kHz each costs about $847/month just in data transfer fees. Add compute, storage, and suddenly your predictive maintenance proof-of-concept is burning through budget faster than the bearings you’re trying to save.
I ran the numbers for a real 100-sensor vibration monitoring deployment—cloud-only vs edge preprocessing vs hybrid—and the cost gap was shocking enough to change the entire architecture.

The Scenario: 100 Accelerometers, 10kHz Each
Industrial vibration monitoring typically uses MEMS accelerometers sampling at 10-25kHz (ISO 10816 recommends at least 3x the highest fault frequency you want to detect). For bearing fault detection, 10kHz is the bare minimum—you need headroom for gear mesh frequencies and harmonics.
Each sensor generates:
With 100 sensors:
That’s just the raw data volume. Now let’s see what happens when you try to process it.
Cloud-Only Architecture: The Naive Approach
The simplest setup: stream everything to AWS, run FFT and envelope analysis in Lambda or EC2, store results in S3.
AWS pricing breakdown (us-east-1, Jan 2026):
- Data transfer out: $0.09/GB for first 10TB = $936/month
- IoT Core messages: 100 sensors × 86400 sec/day × $1.00/million messages = $259/month
- EC2 compute (c6i.2xlarge for real-time FFT): $0.34/hour × 24 × 30 = $245/month
- S3 storage (compressed features, 30-day retention): ~$50/month
- CloudWatch logs: ~$30/month
Total: $8470/month or $8471/year.
And that’s assuming you can keep up. A single c6i.2xlarge instance struggles to process 100 concurrent 10kHz FFT streams in real-time. You’d likely need autoscaling, which pushes costs even higher during peak loads.
But the real killer is data transfer. AWS charges $8472/GB to send data out of the cloud (e.g., to your on-prem SCADA system or HMI dashboard). If you need to mirror processed alerts back to the factory floor, add another $8473-900/month.
Edge-Only Architecture: Raspberry Pi Clusters
What if we run FFT locally and only send features (RMS, peak frequency, kurtosis) to the cloud?
Hardware:
– Raspberry Pi 4 (8GB): ~$8474 each
– 16-channel ADC board (ADS131M08): ~$8475
– Each Pi handles 16 sensors → need 7 Pi units
Upfront cost: 7 × ($8476 + $8477) = $8478
Feature data volume:
Instead of 40KB/s raw data per sensor, we extract 10 features every 10 seconds:
100 sensors × 4 bytes/s = 400 bytes/s = 1 GB/month.
Cloud costs (features only):
– Data transfer: negligible (<$8479)
– IoT Core: 100 × 8640 messages/day × $0.090/million = $0.091/month
– S3 + Lambda for alerting: ~$0.092/month
Total recurring: $0.093/month or $0.094/year.
Add $0.095 upfront hardware. First-year TCO: $0.096.
Compare that to cloud-only: $0.097 vs $0.098 = 14x cost difference.
But Edge Has Hidden Costs You’ll Hit Later
This looks like an obvious win, but here’s what the spreadsheet doesn’t tell you.
1. Maintenance burden
Raspberry Pi units fail. SD cards corrupt (I’ve seen 20% annual failure rates in dusty factory environments). Each site visit costs $0.099+ in technician time. Budget at least 2-3 replacements per year.
2. Algorithm updates are painful
In the cloud, you push a new FFT window size or retrain your RUL model once—it propagates instantly. With edge devices, you’re managing firmware updates across 7 distributed Pi units. I’ve seen factories still running 2-year-old fault detection code because nobody wanted to touch the deployment.
3. Debugging is a nightmare
When a sensor starts reporting garbage, is it ADC noise? A loose cable? Bad FFT implementation? In the cloud, you log everything and replay the pipeline. On edge, you’re SSHing into a Pi mounted 20 feet up on a catwalk.
4. No historical reanalysis
You can’t re-run analysis on raw data you never stored. If you discover a new fault signature six months later (like I did with bearing outer race envelope analysis), you have no way to backtest it.

Hybrid Architecture: The Pragmatic Middle Ground
What if we split the workload intelligently?
Edge (Raspberry Pi):
– Real-time FFT and time-domain features
– Local thresholding for obvious faults (RMS > 5g, peak freq shift > 20%)
– Immediate on-site alarms (no cloud latency)
Cloud (AWS):
– Store compressed raw waveforms for 5% of time windows (triggered by high kurtosis or user request)
– Ensemble models combining multi-sensor features
– Historical trend analysis and RUL prediction
– Centralized model retraining
Data flow:
- Pi computes FFT every 10 sec → extracts 10 features → sends to AWS IoT Core
- If kurtosis > 4 (potential fault), Pi compresses & uploads 1-second raw waveform
- Cloud runs LSTM RUL model on feature time series, flags anomalies
- User can request on-demand raw data pull for any sensor
Cost breakdown:
- Hardware: $9360 upfront (same as edge-only)
- Data transfer: ~5% of sensors trigger raw uploads → 0.5 TB/month → $9361/month
- IoT Core: $9362/month (same as edge-only)
- EC2 (t3.medium for batch RUL inference): $9363/month
- S3 (selective raw storage): $9364/month
Total recurring: $9365/month or $9366/year. First-year TCO: $9367.
This is 8x cheaper than cloud-only while keeping raw data access for debugging and research.
The Cost Curve Breaks at 500+ Sensors
Scaling edge compute isn’t linear. At 500 sensors, you need 32 Raspberry Pi units. Now you’re managing:
- 32 firmware update cycles
- 32 potential failure points
- 32 SSH endpoints to secure
- 32 log aggregation sources
DevOps tax: Assume 1 full-time technician at $9368K/year to manage edge infrastructure at this scale. Suddenly your “cheap” edge setup costs $9369K + $1.000K/year recurring = $1.001K first year.
Meanwhile, cloud autoscaling handles 500 sensors with the same operational complexity as 100 sensors. Cloud-only at 500 sensors: ~$1.002K/year (5x data volume). The gap narrows to $1.003K vs $1.004K—now cloud is only 15% more expensive, with far less ops burden.
At 1000+ sensors, cloud wins on TCO once you factor in personnel costs. This matches what I’ve seen in real deployments—small factories go edge, large multi-site operations go cloud or hybrid.
What About Latency?
Cloud round-trip latency (sensor → AWS → alert) is typically 500-2000ms depending on network.
Edge alert latency: 10-50ms.
Does it matter? For rotating machinery faults, not really—bearing degradation happens over weeks. But for safety-critical shutdown logic (overspeed, overtemp), you want local edge logic with zero cloud dependency. I’d never trust AWS uptime for an emergency stop system.
Rule of thumb: Use edge for <100ms response requirements. Cloud is fine for everything else.
Real-World Hybrid Setup Code
Here’s the Pi-side feature extraction (this runs every 10 seconds on each device):
import numpy as np
from scipy import signal
from scipy.stats import kurtosis
import paho.mqtt.client as mqtt
import json
import time
# Globals
FS = 10000 # 10kHz sampling rate
NFFT = 2048
OVERLAP = 1024
def extract_features(waveform):
"""
Extract 10 time + freq domain features from 1-sec vibration signal.
waveform: np.array of shape (10000,) at 10kHz
"""
# Time domain
rms = np.sqrt(np.mean(waveform**2))
peak = np.max(np.abs(waveform))
crest = peak / (rms + 1e-9) # avoid divide-by-zero
kurt = kurtosis(waveform)
# Frequency domain (Welch PSD)
f, psd = signal.welch(waveform, fs=FS, nperseg=NFFT, noverlap=OVERLAP)
# Dominant frequency (peak in 10-1000 Hz bearing range)
bearing_band = (f >= 10) & (f <= 1000)
peak_freq = f[bearing_band][np.argmax(psd[bearing_band])]
peak_power = np.max(psd[bearing_band])
# Spectral features
spectral_centroid = np.sum(f * psd) / (np.sum(psd) + 1e-9)
spectral_std = np.sqrt(np.sum(((f - spectral_centroid)**2) * psd) / (np.sum(psd) + 1e-9))
# Envelope kurtosis (Hilbert transform for bearing faults)
analytic = signal.hilbert(waveform)
envelope = np.abs(analytic)
env_kurt = kurtosis(envelope)
# High-frequency energy (>2kHz, gear mesh / harmonics)
hf_band = f > 2000
hf_energy = np.sum(psd[hf_band])
return {
'rms': float(rms),
'peak': float(peak),
'crest_factor': float(crest),
'kurtosis': float(kurt),
'peak_freq': float(peak_freq),
'peak_power': float(peak_power),
'spectral_centroid': float(spectral_centroid),
'spectral_std': float(spectral_std),
'envelope_kurtosis': float(env_kurt),
'hf_energy': float(hf_energy)
}
def should_upload_raw(features):
"""Decide if this window is interesting enough to upload raw data."""
# Trigger on high kurtosis (impulsive faults) or sudden freq shift
if features['envelope_kurtosis'] > 4.0:
return True
if features['crest_factor'] > 8.0: # very spiky signal
return True
# TODO: add frequency shift logic (needs historical baseline)
return False
def publish_to_cloud(sensor_id, features, raw_waveform=None):
client = mqtt.Client()
client.connect('your-iot-endpoint.amazonaws.com', 8883)
payload = {
'sensor_id': sensor_id,
'timestamp': int(time.time()),
'features': features
}
if raw_waveform is not None:
# Compress raw waveform (zlib typically 3-4x compression)
import zlib
import base64
compressed = zlib.compress(raw_waveform.tobytes())
payload['raw_data'] = base64.b64encode(compressed).decode('utf-8')
client.publish(f'sensors/{sensor_id}/data', json.dumps(payload))
client.disconnect()
# Main loop (runs continuously on Pi)
if __name__ == '__main__':
sensor_id = 'vibration_pump_01'
while True:
# Read 1 second of data from ADC (10000 samples)
waveform = read_adc_buffer(duration=1.0, fs=FS) # your ADC driver here
features = extract_features(waveform)
# Local threshold alarm (no cloud dependency)
if features['rms'] > 5.0: # 5g RMS = severe fault
trigger_local_alarm(sensor_id, 'HIGH_VIBRATION')
# Send features to cloud always
if should_upload_raw(features):
publish_to_cloud(sensor_id, features, raw_waveform=waveform)
print(f"[{sensor_id}] Uploaded raw waveform (kurtosis={features['envelope_kurtosis']:.2f})")
else:
publish_to_cloud(sensor_id, features)
time.sleep(10) # wait 10 sec before next window
This script runs autonomously on each Pi. The should_upload_raw() logic is the key cost optimization—you only pay cloud transfer fees for the 5% of time windows that look suspicious.
On the cloud side, you’d have a Lambda function subscribing to the IoT Core topic, running a pre-trained LSTM on the feature time series, and pushing alerts to SNS/Slack when RUL drops below threshold. I covered similar pipelines in my real-time FFT alert post.
When the Math Stops Mattering
I’ve seen teams obsess over $/GB pricing tables while ignoring the real question: Who maintains this system in 2 years?
If you’re a 3-person startup building a PHM SaaS product, edge compute is a nightmare—you don’t have the bandwidth to manage distributed hardware. Go cloud-only and focus on your ML models.
If you’re an OEM shipping equipment with embedded monitoring, edge is non-negotiable—you can’t rely on customer network uptime or cloud subscriptions.
If you’re a factory with existing IT staff and 10+ years of equipment lifespan, hybrid makes sense—you get the best of both worlds and the flexibility to shift workloads as cloud pricing changes (and it will).
My Take: Start Hybrid, Measure Everything
For a new 100-sensor deployment, I’d go hybrid:
- Raspberry Pi edge nodes running the feature extraction code above
- Selective raw data upload on anomaly triggers
- Cloud-based RUL models and centralized dashboards
Then measure actual cloud costs for 3 months. If your kurtosis trigger is too sensitive and you’re uploading 30% of raw data instead of 5%, the math flips and you might need smarter edge filtering or a full edge ML model.
The opposite happens too—I’ve seen cases where everything triggered anomalies (noisy factory floor, poor sensor mounting) and they ended up uploading 80% of raw data. At that point, just go cloud-only and fix the sensor installation.
One thing I’m still unsure about: edge ML inference using TensorFlow Lite or ONNX Runtime on the Pi. In theory, you could run a lightweight 1D-CNN fault classifier locally and only upload when the model is uncertain. I haven’t tested this at scale yet—quantized model accuracy on vibration data is hit-or-miss, and debugging model drift on 100 distributed devices sounds painful. But if it works, it could cut cloud costs another 50%.
FAQ
Q: Can I use cheaper SBCs than Raspberry Pi?
Yes, but be careful. I tested Orange Pi 5 ($1.005 faster CPU) and hit driver issues with I2S ADC interfaces—spent a week debugging kernel modules. Pi has better community support. For industrial deployments, consider ruggedized Pi alternatives like the Onlogic Karbon 300 with -40°C to 85°C rating. Cheaper isn’t always cheaper when you factor in failure rates.
Q: What about cellular IoT for remote sites without Ethernet?
LTE-M or NB-IoT modules add $1.006-30/device upfront + $1.007-10/month/SIM for data plans. At 100 sensors, that’s $1.008-1000/month just for connectivity. This tilts heavily toward edge preprocessing—you cannot afford to stream raw 10kHz data over cellular. Feature extraction becomes mandatory, not optional.
Q: How does this change for lower sample rates (1kHz)?
At 1kHz, raw data is 10x smaller (1 TB/month for 100 sensors). Cloud-only costs drop to ~$1.009/month, making it much more viable. But 1kHz is too low for most bearing fault detection (you miss high-frequency harmonics). It works for slow machinery (<300 RPM) or temperature/pressure sensors, but for vibration monitoring, don’t cheap out on sample rate.
The Real Tradeoff: Cost vs Flexibility
Edge wins on recurring cost. Cloud wins on iteration speed and operational simplicity. Hybrid is the pragmatic choice for most deployments, but it requires more upfront engineering to get the edge/cloud split right.
What I’d do differently if I were starting today: build a dynamic data routing system where the Pi can adjust its upload rate based on cloud budget limits. If AWS costs spike, throttle raw uploads automatically. If you’re under budget, increase the upload rate to gather more training data. Treat cloud bandwidth as a tunable resource, not a fixed cost.
The PHM market is still figuring this out. Most vendors lock you into their architecture (pure cloud SaaS or pure edge appliances). The winners will be the ones who let customers dial the cost/flexibility knob based on their actual constraints.
Did you find this helpful?
Your support keeps this blog running and ad-free content coming.
☕ Buy me a coffeeMost Popular Posts
- Custom Metaclass in Python: 43% Faster Validation (12,808 views)
- Python match-case: 7 Patterns That Beat if-elif Chains (951 views)
- YOLOv8 INT8 Quantization: 4x Faster on Jetson Orin (780 views)
- yfinance Alternatives 2026: 7 Free APIs Compared (695 views)
- PaddleOCR vs EasyOCR vs Tesseract: Why PaddleOCR Is Slower (556 views)