DE//AGENT
Explore

Express a freshness check as a metric and an alert

The first hands-on of the series: declare a freshness SLA, express staleness as a metric, and write an alert rule — including what happens when no data arrives at all. Ends with the pre-merge check that keeps schedules honest against the SLA they claim.

At a glance

When You are adding the first data-quality alert for a table; A schedule change is proposed and someone asks what it does to the SLA
Where Data Observability
Why A freshness SLA that lives in a wiki page guards nothing — encode it as a metric and an alert and it defends itself.

Learning objectives

  • Declare a freshness SLA and compute worst-case lag from a schedule
  • Express staleness as a metric and write an alerting rule
  • Configure no-data handling so silence is an alert, not a pass

What you need

  • A table with a declared freshness SLA (in hours)
  • A Prometheus + Grafana stack, or any metrics store with alert rules you can edit

Steps

  1. Declare the contract — a freshness SLA per source, the number the hook can warn against when a change would silently widen it. (from hook-freshness-pre-merge )
  2. Learn the arithmetic the SLA needs — compare the schedule in the diff with the declared SLA and compute the worst-case lag. (from hook-freshness-pre-merge )
  3. Run the example — a cron changed from hourly to daily violates a 6h freshness SLA; the check warns with the computed lag. (from hook-freshness-pre-merge )
  4. Express staleness as a metric — the pull-based metrics model, PromQL, exporters, service discovery and alerting rules are what turn "table age" into a queryable series. (from ref-prometheus-docs )
  5. Trust the semantics — the metrics model and PromQL semantics pages settle how to express and alert on pipeline metrics. (from ref-prometheus-docs )
  6. Put the alert somewhere real — dashboards, panel queries and alerting including the unified alerting model, the surface where pipeline freshness dashboards live. (from ref-grafana-docs )
  7. Handle the silence — alerting semantics (no-data handling, evaluation intervals) are documented precisely; configure them or an absent series passes as health. (from ref-grafana-docs )

Check yourself

  • A daily schedule against a 6h SLA fails by construction — worst-case lag is 24h, not 6h.
  • An absent series is not a healthy one — no-data handling decides whether silence pages you.

Worked example

Staleness as a metric and an alert rule — from ref-prometheus-docs

# illustrative sketch of the model the docs define —
# exporter exposes last success, PromQL computes staleness,
# an alerting rule compares it to the SLA
pipeline_last_success_timestamp{table="orders"}
staleness_seconds = now - pipeline_last_success_timestamp
alert if staleness_seconds > freshness_sla{table="orders"}

The worst-case lag rule — from hook-freshness-pre-merge

Compare the schedule/cron in the diff with the source's declared
freshness SLA. If the new schedule can produce data older than the
SLA (e.g. daily when the SLA is 6h), warn with the computed
worst-case lag.

The no-data decision — from ref-grafana-docs

Alerting semantics to set on every rule — no-data handling and the
evaluation interval. Decide what an absent series means before the
first silent night, not after it.

Sourced from

Security scan

Last sweep 2026-10-24: 0 finding(s), 0 marked as examples.

Common gotchas

  • No-data is not healthy — an absent series under default handling never fires the alert.
  • The evaluation interval adds detection lag — a 6h SLA checked hourly can page an hour late.
  • Design for worst-case lag, not average — a schedule that can emit 24h-old data eventually will.

Production considerations

  • Store the SLA next to the dataset definition so the metric, the alert and the docs share one number.
  • Route data-signal alerts to the table owner from the catalog, not to a shared channel.

Diagram

freshness SLA ──▶ staleness metric ──▶ alert rule
    |
    |- cron × interval ─▶ worst-case lag ─▶ compare to SLA
    |
    |- no-data? ─▶ decide: fire (default) or pass (rare)
    |
    |- pre-merge: cron in diff vs SLA ─▶ warn before it pages anyone

Registry stats

Verification community · Oct 24, 2026
Completeness 81
Trust multiplier ×1.25
Composite 34.15 · adequate
Freshness 0 days since last source check
Difficulty beginner
Version 0.1.0
License CC-BY-4.0
Security flags none