Back to blog

· By Sajeevan (Saj) Veeriah

Industrial data · 4 min read

A connected sensor can still be giving you old data

Separating connection health, measurement age and validity in an MQTT dashboard, with a practical stale-data test.

Illustrative timeline: a sample acquired at 10:00:00 reaches the display at 10:00:08. At 10:00:10 its acquisition age is 10 seconds, although it arrived only 2 seconds ago.
Illustrative timestamps on a shared clock. A recent delivery does not make an old measurement current. View full-size diagram

The dashboard says connected. The temperature is a plausible 22.4 °C. Nothing is red. But when was that temperature actually measured?

A connection indicator can answer whether part of the communication path is available. It cannot, by itself, establish that the displayed value describes the present. This article proposes a way to keep those questions separate in an MQTT-based monitoring system. The device, numbers and tests are fictional examples.

Give the display three separate answers

Start with connection status, measurement age and measurement validity. They can disagree without any contradiction. A device can remain online while its acquisition task is stuck. A healthy sample can arrive after a network interruption. An invalid sensor reading can arrive promptly.

For a proposed payload, include a value and unit, acquisition timestamp, quality flag, device identifier, boot identifier and sequence number. Keep reception time at the consumer as a separate field. Agree what each field means before building a green status badge around it.

A sequence number helps detect repetition or gaps, but needs a restart rule. Sequence 12 after sequence 800 could mean a reboot rather than an old packet. Pairing the counter with a boot identifier makes that distinction inspectable. A repeated numeric value alone is not evidence of a fault: the measured quantity may genuinely be steady.

Treat retained data as a saved observation

MQTT retained messages let a broker provide a stored message to a later subscriber, subject to the subscription's retain-handling setting. That is useful for showing the last known observation when a dashboard opens. It does not establish when the physical measurement was acquired.

MQTT Keep Alive concerns the exchange of protocol control packets. A working ping exchange is not proof that the sensor acquisition task is advancing. Likewise, a Will message can signal a lost connection, but its timing depends on connection detection and configured delay.

Keep the last known value visible when it helps diagnosis, but label its age and quality. Do not turn a missing measurement into zero, or reset its age merely because the dashboard has reconnected.

Sources: [1]

Calculate the age you actually care about

Suppose a sample is acquired at 10:00:00, received at 10:00:08 and viewed at 10:00:10. With synchronised clocks, acquisition age is 10 s. Time since reception is only 2 s. A fictional rule accepting samples up to 5 s old must therefore reject this sample as current.

That arithmetic assumes the timestamps refer to a comparable clock. If the device clock is ahead, subtracting timestamps can produce a negative age. Treat that as a clock-quality problem; silently clamping it to zero would make uncertain data look fresh.

For elapsed time within one running process, use an appropriate monotonic clock. Web performance timing is one documented example of a clock intended to avoid wall-clock adjustments. It does not synchronise a browser with a remote sensor. Cross-device age still needs a defined time reference and an acceptable clock-error bound.

Sources: [2]

Write a freshness rule before choosing colours

This illustrative monitoring policy uses a 5 s age limit. Choose a real limit from how quickly the process changes and what the display is used for.

Write a freshness rule before choosing colours
Observed conditionDisplay and decision
No accepted sample since startupShow unknown; do not supply a default measurement.
Valid sample; trustworthy age from 0 to 5 sShow the value, unit, age and current status.
Valid sample older than 5 sKeep it as last known; clearly mark stale.
Bad quality or untrustworthy acquisition timeMark invalid or age unknown; explain the reason.

Connection status remains separate in every row. Evaluate age periodically, even when no messages arrive. Otherwise the display can remain current indefinitely after the publisher stops. Use text and an icon or shape as well as colour.

Test silence, replay and recovery

MQTT 5 Message Expiry Interval can prevent onward delivery of messages whose protocol lifetime has elapsed. It does not define physical acquisition time, and it cannot invalidate a value already copied into your application's display state. Retain an application-level freshness check.

In an isolated test system, pause acquisition while leaving the MQTT client connected. The value should become stale. Then reconnect a dashboard to a retained old sample: it should show the original age, not a fresh-start timer.

Test a device restart, duplicate sequence, delayed older message, implausible future timestamp and invalid-quality reading. Check that an older observation cannot silently replace the current one. Finally, deliver a new valid sample and verify the defined recovery transition.

Record the displayed status and the underlying timestamps for each case. A screenshot of a connected badge proves very little about measurement freshness; an explicit age and quality policy gives the next engineer something concrete to test.

Sources: [1]

Sources and further reading

Sources checked on 12 September 2026. This is a proposed monitoring design with synthetic timestamps and a fictional 5 s limit, not a validated control or safety function.

  1. OASIS: MQTT Version 5.0, OASIS Standard, 7 March 2019; Keep Alive, RETAIN, Will Delay and Message Expiry sections
  2. W3C: High Resolution Time Level 3, Working Draft, 1 September 2026; monotonic clock and time-origin model
Back to all posts