IoT Software Development: Architecture, Protocols
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
Quick answer. IoT software spans firmware (C/C++, MicroPython, Rust), edge computing, cloud message brokers, time-series pipelines, and user apps. Each layer has costly failure modes: firmware bugs need physical updates and protocol mismatches block data flow. Pick communication protocols and a broker architecture that scales cleanly from 100 to 100,000 devices.
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 1000+ 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.
Inside 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 →
Next Steps
- Manufacturing Software Development
- Computer Vision Development
- Real-Time Application Development
- Cloud Solutions →
Sources
- AWS IoT Core Documentation
- MQTT Specification 5.0
- TimescaleDB Documentation
- InfluxDB 3.0 Documentation
Related: IoT Product Development & Engineering Services — IoT product development from device to cloud.
External Resources
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 1000+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement.
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.