New: the AI firewall watches every module and explains each incident in plain words. See how it works

Timestamps, late and duplicate readings

Which time a reading is stored at, readings from the future or the past, the timestamp settings, duplicates, and readings delayed by an outage.

Every reading is stored at a time. This page explains which time that is, which readings are refused for their time, how duplicates are handled, and what happens to readings that arrive late.

Device time or receive time

What the device sendsStored at
A flat object, for example {"temperature": 21.5}The time the platform received the message
{"ts": 1759572000000, "values": {...}}ts: the device’s own time
An array of the two formsEach element at its own time

ts is an integer of milliseconds since 1 January 1970, UTC. Any other ts (seconds, a string, a negative number) drops that record as bad_ts. See MQTT topics and payload reference.

Send ts only when the device’s clock is synchronised. A device without a reliable clock should send flat objects and let the platform stamp them. A clock that drifts produces readings in the wrong place on charts and can be refused.

In a flow, the record time is msg.metadata.recordTs and the receive time msg.metadata.ts. The Save telemetry block stores the record time by default; its ts setting can switch to the receive time, and ts_path can re-time a record from a value in the message.

Readings from the future

A record timestamped more than 10 minutes ahead of the time it arrives is dropped as bad_ts. It is never corrected to “now”. Change the tolerance in Settings > Telemetry (IoT Telemetry Settings):

SettingDefaultRange
Future timestamp tolerance (minutes)101 to 1,440
Oldest accepted reading (days)0 (any age)0 to 36,500

A record older than Oldest accepted reading (days) before its arrival is dropped as bad_ts. Use it to stop a device from replaying very old buffered data. The page needs the View IoT telemetry settings and Change IoT telemetry settings permissions (Admin by default). Changes reach the ingest within a minute.

Readings from the past

A reading older than your retention class keeps raw data is refused by the store as too_old, whatever the settings above say:

Retention classA reading is refused when older than
7 days7 days
30 days7 days
90 days30 days
365 days90 days
1,095 days90 days

Readings inside the raw window are stored even when they are old, and folded into the minute, hour and day summaries. See How long data is kept.

Duplicates

A device, a gateway or a retry can send the same reading twice. Hermetry handles this at two points:

  1. Before the flow. A device message whose message id was already seen within 60 seconds, or, when it has no id but carries its own ts, whose content was already seen, is acknowledged without a run. A reading with neither an id nor a ts is never treated as a repeat: the same value twice is two readings.
  2. In the store. A message with the same values at the same time for the same device is stored once. A redelivered or replayed message changes nothing.

Two different messages with the same timestamp are both kept. When the API reads raw values, it returns one point per timestamp. The latest value keeps the first one it saw for that timestamp.

Out-of-order readings

A device that buffers readings while offline and sends them later delivers them after newer data. They are stored in the history at their own times. They do not replace a newer latest value. Alarm rules treat records older than the last evaluated one as backfill: they are not evaluated live, and a rule with backfill on records alarms from them without notifying anyone. See Clear conditions and late readings.

Readings delayed by an outage

Messages wait in a queue while a processing worker is down. When the platform catches up, a device message that waited longer than its time-to-live (5 minutes by default) is a late message:

  • It still runs through its root flow and is stored. A backlog is your data, so it is never dropped there.
  • It is marked late (msg.metadata.late). Blocks that act outside the platform skip it: no notification, no device command, no HTTP call or MQTT publish (unless the block’s late setting is send), no emitted event.
  • The Alarm rules block evaluates it as backfill: alarms are written to the history, marked Backfilled, and nobody is paged for the past. An alarm still open when live readings resume is announced then.
  • Other flows that would react to it (for example an alarm listener) drop it and count it as Too old.

See Protections and failed messages.

Time zones

Everything is stored in UTC. The console, dashboards and exports show times in the viewer’s zone. Day rollups run from midnight to midnight UTC; see Aggregates and rollups for reading local days.

Troubleshooting

SymptomLikely cause
A reading is missing, others from the same device are thereIts ts was in the future or out of range (bad_ts), or older than the raw window (too_old). Check the root flow’s run records.
Readings appear hours or a day offThe device sends ts in local time or in seconds. Send UTC milliseconds, or flat objects.
The latest value does not change though new readings arriveThe new readings carry an older or equal ts than the one stored.
A corrected value does not showIt was sent with the same ts as the original; the latest value keeps the first. Send the correction with a new ts.

See also Wrong times and gaps.