The device shadow vs digital twin question comes up in almost every IoT project, because both keep a cloud-side copy of a device's state. This article explains exactly how they differ in scope, data and purpose, shows when a shadow is all you need and when you need a full twin, and walks through a portable device shadow pattern built on retained MQTT topics.
For the twin side in depth, see the digital twin technology guide.
What Is a Device Shadow?
A device shadow is a persistent state document for a single device, held in the cloud. It typically has three parts:
- Reported: the last state the device reported.
- Desired: the state an app wants the device to have.
- Delta: the difference, which the device should act on.
Cloud IoT platforms introduced shadows (also called device twins in some platforms) to solve a specific problem: apps need to read and change device state even when the device is asleep or offline. The shadow is always available; the device syncs with it when it connects.
A shadow is deliberately simple. It knows about one device, holds current state and a version number, and does little else.
What Is a Digital Twin?
A digital twin is a broader concept: a live virtual representation of a physical asset, process or system that combines current state with context and behaviour. On top of the state a shadow holds, a twin typically adds:
- A model: what the asset is, its properties, units and semantics, often expressed in DTDL or as an Asset Administration Shell.
- Relationships: this pump belongs to that station, which feeds that tank.
- History: time series used for trends, diagnostics and prediction.
- Analytics or simulation: derived values, anomaly detection, what-if scenarios.
- Visualization: dashboards or 3D scenes showing many assets together.
A twin can represent things that are not a single device at all: a production line, a building floor, a whole plant.
Device Shadow vs Digital Twin: Side-by-Side
| Aspect | Device shadow | Digital twin |
|---|---|---|
| Scope | One device | Asset, system or process, often many devices |
| Core data | Current reported and desired state | State plus history, model and context |
| Model | Free-form JSON | Explicit schema, semantics and units |
| Relationships | None | Hierarchies and links between assets |
| Time | Latest value only | Current and historical |
| Logic | Delta computation | Analytics, simulation, prediction |
| Typical consumers | Mobile apps, device management | Engineers, operators, planners |
| Visualization | Usually none | Dashboards and 3D views common |
| Effort to build | Low | Medium to high |
The relationship is cumulative: most digital twins contain something shadow-like for each device, while a shadow on its own is not a full twin. Our article on digital twin vs digital shadow covers a related but different distinction from the research literature, where a digital shadow means one-way data flow from asset to model.
When a Device Shadow Is Enough
Choose a shadow when:
- You manage many similar devices, such as smart plugs, trackers or meters.
- The main need is "show current state and let me change settings".
- Devices sleep or connect intermittently and must catch up on configuration.
- You do not need relationships between devices or analytics on top.
Consumer IoT, fleet configuration and remote settings are classic shadow territory.
When You Need a Full Digital Twin
Choose a twin when:
- Value comes from seeing assets in context: a line, a building, a grid.
- You need to correlate state with history to diagnose problems.
- Multiple data sources describe one asset (PLC, vibration sensor, MES).
- Users want spatial or 3D views.
- You plan predictive maintenance or simulation.
Industrial plants, energy systems and buildings almost always end up here. The digital twin architecture article shows the extra layers you will need.
Building a Portable Device Shadow with Retained MQTT Topics
Cloud shadow services are tied to their platform. You can get the same behaviour on any standards-compliant MQTT broker using retained messages, which keeps the design portable. The topic layout:
connectmq/demo/<id>/shadows/<device>/reported retained, device writes
connectmq/demo/<id>/shadows/<device>/desired retained, apps write
connectmq/demo/<id>/shadows/<device>/delta not retained, computed by a shadow service
connectmq/demo/<id>/shadows/<device>/status retained, last will
Retained messages give you the most important shadow property for free: whoever subscribes, whenever they subscribe, receives the latest reported and desired documents. A small service computes deltas:
import json
import paho.mqtt.client as mqtt
BASE = "connectmq/demo/4d2a/shadows"
shadows = {}
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe(f"{BASE}/+/reported", qos=1)
client.subscribe(f"{BASE}/+/desired", qos=1)
def on_message(client, userdata, msg):
_, _, _, _, device, kind = msg.topic.split("/")
doc = json.loads(msg.payload) if msg.payload else {}
shadow = shadows.setdefault(device, {"reported": {}, "desired": {}})
shadow[kind] = doc
delta = {
key: value
for key, value in shadow["desired"].items()
if key not in ("version", "ts") and shadow["reported"].get(key) != value
}
if delta:
client.publish(f"{BASE}/{device}/delta", json.dumps(delta), qos=1)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="shadow-service-4d2a")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883)
client.loop_forever()
Try it with the free public MQTT broker:
mosquitto_pub -h broker.connectmq.com -p 1883 -i lamp1-4d2a -q 1 -r \
-t "connectmq/demo/4d2a/shadows/lamp1/reported" -m '{"on": false, "brightness": 40}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i app-4d2a -q 1 -r \
-t "connectmq/demo/4d2a/shadows/lamp1/desired" -m '{"version": 1, "on": true, "brightness": 80}'
mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-4d2a \
-t "connectmq/demo/4d2a/shadows/lamp1/#" -v
The service publishes {"on": true, "brightness": 80} to the delta topic. A device can also skip the service entirely: it subscribes to its retained desired topic and computes the delta locally, which is often simpler for small fleets. The reconnect and versioning rules from digital twin state synchronization apply unchanged.
Limits of the Retained-Topic Shadow
Be honest about what this pattern does not give you. There is no query API ("find all lamps that are on"), no per-document access control beyond what your broker credentials allow, and retained messages live in the broker rather than a database. If you need those, add a twin service or database subscriber alongside the broker. For many fleets, though, retained topics are enough and avoid an entire service tier.
Common Mistakes When Choosing Between Them
Teams tend to make one of two opposite mistakes. The first is calling a shadow a twin and then being surprised when stakeholders expect history, context and analytics that a single state document cannot provide. If the plant manager asks "why did line 3 slow down last Tuesday?", a shadow has no answer.
The second mistake is starting with a heavyweight twin platform when the actual requirement is "let the mobile app change the thermostat setpoint while the device sleeps". That project needs a shadow, and adding modelling, graph databases and 3D scenes only delays delivery.
A useful test is to write down the three questions users most want answered. If all three are about the current state or configuration of one device, build a shadow. If any of them involve time, relationships between assets or comparing expected and actual behaviour, plan for a twin, but still start with the shadow-style state topics described above, because the twin will be built on top of them.
From Shadow to Twin: A Practical Path
- Start with a retained reported and desired topic per device.
- Add a status topic with last will for presence.
- Add a history subscriber writing to a time-series database.
- Introduce an asset model with hierarchy and units.
- Add a dashboard or 3D view that subscribes to whole branches.
- Layer analytics on history and live state.
Each step reuses the same topics, so devices never need to change.
Build Shadows and Twins on ConnectMQ
ConnectMQ gives you the messaging foundation for both: a hosted MQTT broker with retained messages, last will, MQTT 3.1.1 and 5.0, TLS on 8883 and WSS on 8084 for browser dashboards. Your shadow logic and twin services connect as ordinary MQTT clients, so nothing is locked to one cloud. Create a free Serverless broker at app.connectmq.com, with no credit card, and move your first device shadow onto it.
Frequently Asked Questions
Is a device shadow a digital twin?
A device shadow is a simple form of twin-like state for one device. A digital twin adds a model, relationships, history and analytics, often across many devices.
Can I build a device shadow without a cloud IoT platform?
Yes. Retained MQTT topics for reported and desired state, plus an optional delta service, reproduce shadow behaviour on any standards-compliant MQTT broker.
What is the difference between a device twin and a device shadow?
They are essentially the same concept with different platform names: a cloud-side document with reported and desired properties for one device.
Do I need a database for a device shadow?
Not necessarily. Retained messages hold the latest state. Add a database when you need queries across devices, history or audit trails.



