Delayed data arrives on purpose, late by a known amount. Stale data was supposed to be current and is not. The first is something you can build around; the second is something that will quietly ruin a decision.
Why delay is fine
A delayed feed is honest as long as the delay is stated and constant. Fifteen-minute quotes are perfectly usable for anything measured in hours, and an aggregate that recomputes hourly is fine for structure that moves on a daily scale. You know what you are getting, and you can decide whether it fits.
The problem only starts when the delay is undeclared, because then you assume zero. A screen showing a number with no timestamp is implicitly claiming it is current, and that claim is often false.
How staleness hides
Staleness rarely announces itself. An upstream source stops responding, a cache keeps serving the last good value, and the number on the screen looks completely normal. It has the right shape, a plausible magnitude, and no indication that it stopped moving forty minutes ago.
This is why a timestamp on the reading matters more than almost any other field. Not the time the response was assembled — that is always now and tells you nothing — but the time the underlying measurement was taken.
Ask for the age, not the timestamp
The most practical form is an age in seconds alongside the reading. It requires no clock-skew reasoning on your end and it is trivially checkable: if the age exceeds what you can tolerate, stop trusting the number.
Better still is knowing what kind of reading it is. Computed just now, retrieved from a source that publishes weekly, or unknown. Those are three different confidence levels wearing one number.