DEV Community

137Foundry
137Foundry

Posted on

How to Build a Freshness Check That Runs Before Your Dashboard Loads

Most dashboards render whatever data happens to be in the table, with no check on whether that data is actually current. Here's a practical pattern for adding a freshness check that runs before the dashboard renders, so users get an explicit signal instead of a silent assumption.

Step 1: Store a Last-Updated Timestamp Alongside the Data

The pipeline that populates the dashboard's tables should also write a small metadata row: which table it updated, and the timestamp of the newest record it processed. This doesn't need its own service. A single row in a lightweight metadata table, updated at the end of every successful pipeline run, is enough.

def record_freshness(table_name, newest_record_ts):
    db.execute(
        "INSERT INTO freshness_log (table_name, updated_at, newest_record_ts) "
        "VALUES (%s, NOW(), %s) "
        "ON CONFLICT (table_name) DO UPDATE SET "
        "updated_at = NOW(), newest_record_ts = EXCLUDED.newest_record_ts",
        (table_name, newest_record_ts)
    )
Enter fullscreen mode Exit fullscreen mode

Step 2: Query Freshness Before the Dashboard Query Runs

On page load, query the freshness table first, before running the expensive dashboard query itself. This is a cheap, single-row lookup, so it adds negligible latency, and it gives you the information you need to decide what to show the user.

def get_freshness(table_name):
    row = db.query_one(
        "SELECT newest_record_ts FROM freshness_log WHERE table_name = %s",
        (table_name,)
    )
    return row["newest_record_ts"] if row else None
Enter fullscreen mode Exit fullscreen mode

Step 3: Compare Against Your Defined SLA Window

Compute how old the data actually is, and compare it against whatever freshness window the dashboard is supposed to guarantee. This threshold should come from an explicit decision about what the data is used for, not an arbitrary round number.

from datetime import datetime, timezone

def freshness_status(newest_record_ts, sla_minutes):
    age = (datetime.now(timezone.utc) - newest_record_ts).total_seconds() / 60
    if age <= sla_minutes:
        return "fresh"
    elif age <= sla_minutes * 1.5:
        return "warning"
    return "stale"
Enter fullscreen mode Exit fullscreen mode

Step 4: Surface the Result in the UI, Not Just the Logs

The whole point of this check is that a human sees the result, not just a monitoring system. Render a small, unavoidable indicator, "updated 4 minutes ago" for a fresh state, a visible warning banner for a stale one, so the user makes their own judgment call about whether to trust what they're looking at instead of assuming it by default.

Step 5: Pipe the Same Signal Into Your Alerting Stack

The same freshness check that powers the UI indicator should feed your monitoring system too, so engineering finds out about a stale pipeline the same moment a user would, or ideally before. A metrics backend like Prometheus can scrape this value on an interval and alert when it crosses your threshold, and a dashboard built in Grafana can plot it over time so a slow creep toward staleness is visible as a trend, not just a binary pass or fail.

Step 6: Test It With a Deliberately Stale Fixture

Write a test that seeds the freshness table with an old timestamp and confirms the dashboard actually shows the warning state, not just that the happy path works. Python's standard library documentation covers the unittest.mock patterns useful for freezing time in a test like this, since freshness checks are inherently time-dependent and easy to get wrong without deliberately testing the boundary.

Step 7: Handle the Case Where Freshness Data Itself Is Missing

Don't assume the freshness table will always have a row. A brand-new table, a renamed pipeline, or a one-off backfill job that skips the metadata write will all leave get_freshness returning nothing. Decide explicitly what the dashboard shows in that case, ideally an honest "freshness unknown" state rather than silently falling back to treating missing data as fresh. Failing open on a freshness check defeats the entire purpose of building one.

def render_freshness_badge(table_name, sla_minutes):
    ts = get_freshness(table_name)
    if ts is None:
        return "freshness unknown"
    return freshness_status(ts, sla_minutes)
Enter fullscreen mode Exit fullscreen mode

Step 8: Account for Multiple Tables Feeding One Dashboard

Most real dashboards aren't backed by a single table. A page showing order volume alongside inventory levels is really two freshness stories layered on top of each other, and they can diverge, one feed running perfectly on time while the other has quietly stalled. Track freshness per source table, not once per dashboard, and roll them up so the UI shows the staleness of whichever underlying feed is worst, rather than an average that hides the one that's actually broken.

def dashboard_freshness_status(table_names, sla_minutes):
    statuses = [freshness_status(get_freshness(t), sla_minutes) for t in table_names]
    if "stale" in statuses:
        return "stale"
    if "warning" in statuses:
        return "warning"
    return "fresh"
Enter fullscreen mode Exit fullscreen mode

Step 9: Cache the Freshness Lookup Carefully

The freshness query is cheap, but on a high-traffic dashboard it's still an extra database round trip on every page load. Cache the result for a short window, ten to thirty seconds is usually plenty, rather than caching it for as long as the SLA window itself, which would let the cached "fresh" answer outlive the actual freshness it's supposed to represent. Getting this cache duration wrong in the generous direction quietly reintroduces exactly the problem this whole feature exists to solve.

from functools import lru_cache
import time

_cache = {}

def get_freshness_cached(table_name, ttl_seconds=15):
    now = time.time()
    cached = _cache.get(table_name)
    if cached and now - cached[1] < ttl_seconds:
        return cached[0]
    value = get_freshness(table_name)
    _cache[table_name] = (value, now)
    return value
Enter fullscreen mode Exit fullscreen mode

Step 10: Roll It Out to One Dashboard Before Templating It

Resist the urge to build a generic freshness component for every dashboard in the company on day one. Ship it on the single dashboard that's caused the most confusion, watch how the warning and stale states actually get used in practice, and adjust the thresholds based on real feedback before extracting it into a shared component. A freshness indicator that's technically correct but tuned wrong, warning constantly on a dashboard where five-minute staleness is genuinely fine, teaches users to ignore it, which defeats the point just as thoroughly as not building it at all.

A Note on Framework-Specific Implementation

The examples above are deliberately framework-agnostic pseudocode. In a real app, the freshness lookup fits naturally into whatever data-loading pattern the frontend already uses, a server-side loader function, a REST endpoint the dashboard polls, or a resolver in a GraphQL schema. The specific plumbing matters less than the underlying discipline: compute freshness from real data, not from job status, cache it briefly rather than for the full SLA window, and fail toward an honest "unknown" state rather than a false "fresh" one when the freshness table itself is empty or unreachable.

What This Buys You

Once this check exists, "is this data current" stops being a question someone has to ask in a channel and becomes something the dashboard answers for itself, every time it loads. It's a small amount of engineering work that removes a recurring category of trust problem. If you want the fuller picture on setting the SLA number this check is actually measured against, and how to alert before you breach it rather than after, we cover that in our guide on designing a data freshness SLA for automation pipelines, the kind of end-to-end reliability work 137Foundry's engineering team builds for clients regularly.

Top comments (0)