IoT Software Development: Architecture, Protocols, and Cloud Integration
IoT software development in 2026 — MQTT vs HTTP protocols, AWS IoT Core, device management, time-series data pipelines, edge computing, and production IoT archi
IoT Software Development: Architecture, Protocols, and Cloud Integration
IoT software is where embedded systems, cloud infrastructure, data engineering, and user-facing applications converge. Getting any layer wrong creates problems that are expensive to fix: firmware bugs require physical device updates, protocol mismatches block data flow, and poorly designed data pipelines become bottlenecks at scale.
This guide covers the complete IoT stack: device communication protocols, cloud message brokers, time-series data pipelines, edge computing patterns, and the architecture decisions that scale from 100 to 100,000 devices.
The IoT Stack
┌────────────────────────────────────────────────────┐
│ Devices (sensors, actuators, gateways) │
│ Firmware: C/C++, MicroPython, Rust │
├────────────────────────────────────────────────────┤
│ Edge Layer (optional) │
│ Local processing, protocol translation, buffering │
│ Runtime: Raspberry Pi, NVIDIA Jetson, AWS Greengrass│
├────────────────────────────────────────────────────┤
│ Transport Layer │
│ MQTT, HTTPS, CoAP, WebSocket │
├────────────────────────────────────────────────────┤
│ Cloud Message Broker │
│ AWS IoT Core, Azure IoT Hub, EMQX, Mosquitto │
├────────────────────────────────────────────────────┤
│ Data Pipeline │
│ Kinesis/Kafka → Lambda/Flink → Time-series DB │
├────────────────────────────────────────────────────┤
│ Storage │
│ InfluxDB, TimescaleDB, AWS Timestream, S3 │
├────────────────────────────────────────────────────┤
│ Applications │
│ Dashboards, alerts, ML inference, APIs │
└────────────────────────────────────────────────────┘
Protocol Selection
MQTT (Message Queuing Telemetry Transport)
The dominant IoT protocol. Lightweight, publish-subscribe, designed for constrained networks.
Key properties:
- Binary protocol — very small packet overhead (~2 bytes minimum header)
- QoS levels: 0 (fire and forget), 1 (at least once), 2 (exactly once)
- Persistent sessions — broker queues messages when device is offline
- Topics: hierarchical strings (
factory/line-a/machine-3/temperature) - Wildcard subscriptions:
factory/+/machine-3/#(+ = single level, # = multi-level)
Use MQTT when: Battery-powered devices, constrained bandwidth, reliable delivery needed, fan-out messaging (one message → many subscribers)
HTTP/HTTPS
Request-response. Simple to implement, works through standard proxies.
Use HTTP when: Devices have reliable connectivity, payload sizes are large, request-response interaction pattern, REST APIs are easier for the team to implement
CoAP (Constrained Application Protocol)
UDP-based, designed for very constrained devices (microcontrollers with <10KB RAM).
Use CoAP when: Devices are extremely resource-constrained, UDP is acceptable, multicast discovery needed
Protocol Comparison
| Protocol | Transport | Battery Impact | Overhead | Best For |
|---|---|---|---|---|
| MQTT | TCP | Low | ~2 bytes header | Battery devices, fan-out |
| HTTPS | TCP | Medium | ~300 bytes headers | Reliable networks, large payloads |
| CoAP | UDP | Very low | ~4 bytes header | Microcontrollers, LAN |
| WebSocket | TCP | Medium | ~6 bytes frame | Bidirectional, real-time control |
🌐 Looking for a Dev Team That Actually Delivers?
Most agencies sell you a project manager and assign juniors. Viprasol is different — senior engineers only, direct Slack access, and a 5.0★ Upwork record across 100+ projects.
- React, Next.js, Node.js, TypeScript — production-grade stack
- Fixed-price contracts — no surprise invoices
- Full source code ownership from day one
- 90-day post-launch support included
MQTT Implementation
Device (Python/MicroPython)
import paho.mqtt.client as mqtt
import json
import time
import ssl
BROKER = "your-iot-endpoint.iot.us-east-1.amazonaws.com"
PORT = 8883
DEVICE_ID = "sensor-001"
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to broker")
# Subscribe to device commands on connect
client.subscribe(f"devices/{DEVICE_ID}/commands", qos=1)
else:
print(f"Connection failed: {rc}")
def on_message(client, userdata, msg):
"""Handle incoming commands from cloud."""
command = json.loads(msg.payload)
if command.get('action') == 'restart':
restart_device()
elif command.get('action') == 'set_interval':
update_reading_interval(command['interval_seconds'])
def on_disconnect(client, userdata, rc):
if rc != 0:
print(f"Unexpected disconnect: {rc}. Will retry...")
client = mqtt.Client(client_id=DEVICE_ID, clean_session=False)
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
# TLS mutual authentication (required for AWS IoT Core)
client.tls_set(
ca_certs="/certs/AmazonRootCA1.pem",
certfile=f"/certs/{DEVICE_ID}-certificate.pem.crt",
keyfile=f"/certs/{DEVICE_ID}-private.pem.key",
tls_version=ssl.PROTOCOL_TLSv1_2,
)
client.connect(BROKER, PORT, keepalive=60)
client.loop_start()
def publish_reading(temperature: float, humidity: float):
payload = json.dumps({
"deviceId": DEVICE_ID,
"timestamp": time.time(),
"temperature": round(temperature, 2),
"humidity": round(humidity, 2),
"unit": "celsius",
})
result = client.publish(
topic=f"sensors/{DEVICE_ID}/telemetry",
payload=payload,
qos=1, # At least once delivery
retain=False,
)
if result.rc != mqtt.MQTT_ERR_SUCCESS:
print(f"Publish failed: {result.rc}")
# Buffer locally and retry on reconnect
# Main loop
while True:
temp, humidity = read_sensors()
publish_reading(temp, humidity)
time.sleep(30) # Publish every 30 seconds
Cloud: AWS IoT Core with Rules Engine
# Terraform: AWS IoT Core setup
resource "aws_iot_topic_rule" "sensor_data" {
name = "sensor_telemetry_to_kinesis"
enabled = true
sql = "SELECT * FROM 'sensors/+/telemetry'"
sql_version = "2016-03-23"
# Route to Kinesis for stream processing
kinesis {
role_arn = aws_iam_role.iot_kinesis.arn
stream_name = aws_kinesis_stream.iot_data.name
partition_key = "deviceId"
}
# Also store raw messages in S3 for replay
s3 {
role_arn = aws_iam_role.iot_s3.arn
bucket_name = aws_s3_bucket.iot_raw.id
key = "raw/\${topic()}/\${timestamp()}.json"
}
# Alert on anomalies via SNS
error_action {
sns {
role_arn = aws_iam_role.iot_sns.arn
target_arn = aws_sns_topic.iot_errors.arn
}
}
}
resource "aws_kinesis_stream" "iot_data" {
name = "iot-sensor-data"
shard_count = 4 # 4 MB/s ingest, 4000 records/s
retention_period = 24 # Hours
stream_mode_details {
stream_mode = "PROVISIONED"
}
}
Time-Series Data Pipeline
IoT data is fundamentally time-series: each reading has a timestamp and one or more values. Standard relational databases handle this poorly at scale.
TimescaleDB (PostgreSQL Extension)
-- TimescaleDB: PostgreSQL with time-series superpowers
-- Regular PostgreSQL table creation
CREATE TABLE sensor_readings (
time TIMESTAMPTZ NOT NULL,
device_id TEXT NOT NULL,
metric TEXT NOT NULL,
value DOUBLE PRECISION NOT NULL,
unit TEXT
);
-- Convert to hypertable (automatically partitions by time)
SELECT create_hypertable('sensor_readings', 'time', chunk_time_interval => INTERVAL '1 day');
-- Compression (90% storage reduction for older data)
ALTER TABLE sensor_readings SET (
timescaledb.compress,
timescaledb.compress_orderby = 'time DESC',
timescaledb.compress_segmentby = 'device_id'
);
-- Auto-compress chunks older than 7 days
SELECT add_compression_policy('sensor_readings', INTERVAL '7 days');
-- Efficient time-range queries (uses time-based partitioning)
SELECT
time_bucket('5 minutes', time) AS bucket,
device_id,
metric,
AVG(value) AS avg_value,
MIN(value) AS min_value,
MAX(value) AS max_value
FROM sensor_readings
WHERE device_id = 'sensor-001'
AND metric = 'temperature'
AND time >= NOW() - INTERVAL '24 hours'
GROUP BY bucket, device_id, metric
ORDER BY bucket DESC;
InfluxDB 3.0 (Purpose-Built)
from influxdb_client_3 import InfluxDBClient3
from datetime import datetime, timezone
client = InfluxDBClient3(
host="https://us-east-1-1.aws.cloud2.influxdata.com",
token=INFLUX_TOKEN,
database="iot-sensors"
)
# Write telemetry data
def write_telemetry(device_id: str, readings: dict):
record = {
"measurement": "sensor_telemetry",
"tags": {
"device_id": device_id,
"location": readings.get("location", "unknown"),
},
"fields": {
"temperature": readings["temperature"],
"humidity": readings["humidity"],
"battery_level": readings.get("battery", 100.0),
},
"time": datetime.now(timezone.utc),
}
client.write(record=record)
# Query with SQL (InfluxDB 3.0 supports SQL)
df = client.query("""
SELECT
DATE_TRUNC('minute', time) AS minute,
device_id,
AVG(temperature) AS avg_temp,
MAX(temperature) AS max_temp
FROM sensor_telemetry
WHERE device_id = 'sensor-001'
AND time >= NOW() - INTERVAL '1 hour'
GROUP BY 1, 2
ORDER BY 1 DESC
""", language="sql")
🚀 Senior Engineers. No Junior Handoffs. Ever.
You get the senior developer, not a project manager who relays your requirements to someone you never meet. Every Viprasol project has a senior lead from kickoff to launch.
- MVPs in 4–8 weeks, full platforms in 3–5 months
- Lighthouse 90+ performance scores standard
- Works across US, UK, AU timezones
- Free 30-min architecture review, no commitment
Edge Computing
Edge computing runs processing on local hardware (gateway or edge server) instead of sending everything to the cloud. Benefits: reduced latency, lower bandwidth costs, operation during connectivity loss.
# Edge inference example: anomaly detection runs locally
# Only sends alerts to cloud, not raw data stream
import numpy as np
from collections import deque
class EdgeAnomalyDetector:
def __init__(self, window_size: int = 60, threshold_std: float = 3.0):
self.window = deque(maxlen=window_size)
self.threshold = threshold_std
self.cloud_client = MQTTClient()
def process_reading(self, device_id: str, value: float, timestamp: float):
self.window.append(value)
if len(self.window) < 10:
return # Not enough data yet
mean = np.mean(self.window)
std = np.std(self.window)
z_score = abs(value - mean) / (std + 1e-8)
if z_score > self.threshold:
# Anomaly detected — send alert to cloud immediately
self.cloud_client.publish(
f"alerts/{device_id}/anomaly",
payload={
"deviceId": device_id,
"value": value,
"mean": mean,
"zScore": z_score,
"timestamp": timestamp,
},
qos=1,
)
# Only send raw data every 5 minutes (not every reading)
# This reduces bandwidth by 90% vs streaming everything
if timestamp % 300 < 1:
self.cloud_client.publish(
f"sensors/{device_id}/telemetry",
payload={"value": value, "timestamp": timestamp},
qos=0, # Best effort for non-critical data
)
Device Management
// Device shadow: desired state vs. reported state pattern
interface DeviceShadow {
desired: {
reportingIntervalSeconds: number;
alertThreshold: number;
firmwareVersion: string;
};
reported: {
reportingIntervalSeconds: number;
alertThreshold: number;
firmwareVersion: string;
batteryLevel: number;
lastSeen: string;
};
delta?: {
// Present when desired !== reported
reportingIntervalSeconds?: number;
firmwareVersion?: string;
};
}
// Update desired state — device applies on next connection
async function updateDeviceConfig(deviceId: string, config: Partial<DeviceShadow['desired']>) {
await iotClient.send(new UpdateThingShadowCommand({
thingName: deviceId,
payload: JSON.stringify({
state: { desired: config },
}),
}));
}
IoT Project Cost Ranges (2026)
| Scope | Devices | Timeline | Investment |
|---|---|---|---|
| Proof of concept | 1–10 | 4–8 weeks | $15,000–$30,000 |
| Small deployment | 10–100 | 8–16 weeks | $40,000–$100,000 |
| Medium deployment | 100–1,000 | 4–8 months | $100,000–$300,000 |
| Large deployment | 1,000–50,000 | 6–18 months | $300,000–$1M+ |
Monthly cloud costs: ~$0.08–$0.50 per device per month for AWS IoT Core + data storage at moderate telemetry rates.
Working With Viprasol
We build IoT software stacks — from device firmware guidance through cloud message brokers, time-series data pipelines, edge computing, and real-time dashboards.
→ IoT project discussion →
→ Software Development Services →
→ AI & Machine Learning →
About the Author
Viprasol Tech Team
Custom Software Development Specialists
The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.
Need a Modern Web Application?
From landing pages to complex SaaS platforms — we build it all with Next.js and React.
Free consultation • No commitment • Response within 24 hours
Need a custom web application built?
We build React and Next.js web applications with Lighthouse ≥90 scores, mobile-first design, and full source code ownership. Senior engineers only — from architecture through deployment.