C.W.K.
Stream
Lesson 05 of 05 · published

Stale Stays Visible

~10 min · staleness, caching, calm-ui, freshness

Level 0Open Gate
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Old data isn't a problem to hide. It's a fact to label. The lie is pretending it's fresh."

What to do when data gets old

Data ages. A quote from this morning is stale by afternoon; a value from last Friday is stale after a long weekend. A high-trigger app treats staleness as an emergency — it flashes, it urgently re-fetches, it hides the old number. Keep does the calm thing: stale data remains visible and labelled instead of vanishing. The old value stays on screen, wearing its age honestly — "as of this date, this many hours old" — so you can see both the number and exactly how much to trust it. Nothing disappears, nothing screams, nothing pretends to be fresher than it is.

Why hiding stale data is the worse option

Two apps, same stale quote. App A hides it and shows a spinner until a fresh value arrives — but the provider is down, so you stare at a blank where your portfolio should be, anxious. App B shows the last known value with a clear "4 hours old" tag — you have the information and its exact caveat, and you're calm. Hiding stale data doesn't protect the user from anything; it just replaces a labelled fact with an anxious void. The honest label is both more useful and more calming than the hidden truth.

Label uncertainty; never hide it. A user shown a stale value with its age can reason correctly. A user shown a blank, a spinner, or a stale value disguised as fresh cannot. Freshness metadata isn't clutter — it's the difference between a number someone can act on responsibly and one that will eventually betray them.

Caching without changing policy

Keep caches provider data to avoid hammering the sources, and the cache windows are chosen to match how fast each kind of data actually changes:

  • Daily bars → cached for a day (they don't change intraday)
  • Sparkline windows → an hour
  • Fundamentals → six hours (they move slowly)
  • Derived simulation calibration → a day

Caching speeds things up without changing policy — a cached value is still shown with honest provenance and age. And one deliberate exception: seed prices for a simulation run are always resolved fresh at run time, never served from cache, because a scenario's starting point must be exact and reproducible (you'll see why in the next track).

Cache windows encode a belief about change rate. A one-day cache on daily bars and a one-hour cache on sparklines aren't arbitrary — each says 'this kind of data doesn't meaningfully change faster than this.' Choosing a cache TTL is really choosing a claim about volatility, and getting it wrong means either stale-looking data or needless load. Match the TTL to the data's real tempo.

Code

Cache TTLs match each data type's real tempo·python
CACHE_TTL = {
    "daily_bars":         24 * 3600,   # bars don't move intraday
    "sparkline":           1 * 3600,   # short windows, refresh hourly
    "fundamentals":        6 * 3600,   # slow-moving
    "sim_calibration":    24 * 3600,   # derived, stable for a day
}

def get(kind, key):
    hit = cache.get(kind, key)
    if hit and hit.age < CACHE_TTL[kind]:
        return hit.with_age_label()      # cached, but shown WITH its age
    return fetch_and_cache(kind, key)

# Seed prices for a simulation are the deliberate exception:
# ALWAYS resolved fresh at run time, never from cache. Reproducibility
# requires an exact, re-resolvable starting point.

External links

Exercise

Pick a value your UI shows that comes from an external source. Decide its honest cache TTL by asking 'how fast does this actually change?' Then design its stale state: instead of hiding it or showing a spinner, what label makes the age honest and the user calm? Contrast the anxiety of App A (hides stale, shows a void when the source is down) with the calm of App B (shows the last value, clearly aged).
Hint
The TTL question is really 'what's the fastest meaningful change rate?' A daily close can cache for a day; a live tick for seconds. And for the stale state: a user who can see 'this is 4 hours old' trusts your tool more than one who sees a blank — transparency about staleness builds confidence, hiding it destroys it the first time they catch you.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.