Explain how a Grafana dashboard's time range and refresh setting reach an individual panel's query, including what the $__interval and $__rate_interval macros resolve to and how the Max data points and Min interval query options affect them.
answer
- from/to live in the URL; pin absolute before sharing
- interval = range ÷ maxDataPoints, floored by min interval
- max data points defaults to panel pixel width
- $__rate_interval ≈ max(interval + scrape, 4 × scrape)
- refresh re-runs every visible panel — load multiplier
basics
~20 sThe dashboard time range (from/to, also in the URL) is sent with every panel query. Grafana computes an interval = range ÷ max data points, floored by Min interval, and exposes it as $__interval; $__rate_interval widens it to guarantee enough samples. Auto-refresh re-runs every panel.
solid answer
~50 sOne dashboard-level time range — relative (`now-6h` to `now`) or absolute, plus a timezone — is sent with every panel query as `from`/`to`, and lives in the URL so a link reproduces the view. A panel may override it with **Relative time** (its own window) or **Time shift** (the same window moved back, for week-over-week comparisons). Grafana also computes a step and passes it down: `interval = max(timeRange / maxDataPoints, minInterval, the data source's own minimum step)`, rounded up to a friendly unit. **Max data points** defaults to the panel's pixel width — more points than pixels is wasted work. That value is what `$__interval` expands to; `$__interval_ms` is the same in milliseconds, and `$__from`/`$__to` give the raw epoch bounds. `$__rate_interval` exists because a rate over exactly one scrape interval yields nothing: it is roughly `max($__interval + scrape interval, 4 × scrape interval)`, guaranteeing several samples per window. Auto-refresh re-runs **every** panel on the dashboard, so the interval is a load multiplier, floored server-side by a minimum-refresh setting.
code
text · 9 linesrange = 6h (21600s), maxDataPoints = 1000, minInterval unset
21600 / 1000 = 21.6s -> rounded up -> $__interval = 30s
scrape interval = 15s
$__rate_interval = max(30s + 15s, 4 x 15s) = max(45s, 60s) = 1m
zoom out to 30d, same panel width:
2592000 / 1000 = 2592s -> $__interval = 1h (backend aggregates instead
of shipping millions of points)go deeper
Know that the dashboard time range applies to all panels, that it is in the URL, and that the interval macro adapts the query step to the selected range.
Derive the interval from range, max data points and min interval, and explain why max data points defaults to panel width and why rate windows need a wider interval.
Reason about refresh as a load multiplier across panels and viewers, about the incomplete-last-bucket artefact and the now delay, and about pinning absolute ranges for shareable evidence.
Set instance-wide policy: allowed refresh intervals, defaults for wall dashboards versus investigation dashboards, and the resolution budget a backend can sustain across the dashboard estate.
## One time range, many queries A Grafana dashboard has a single time range shared by its panels. It is either **relative** (`now-6h` → `now`, re-evaluated on each execution) or **absolute** (two fixed instants), and it is carried in the URL as `from` and `to`, which is why pasting a dashboard link into an incident channel reproduces exactly what you were looking at — provided you pin the range absolutely first. A relative link shows the reader *their* now, not yours. The range is accompanied by a timezone (browser local, UTC, or a dashboard-pinned zone). Timezone affects bucket boundaries for anything grouped by day, so a "daily" panel can disagree with a report simply because the two use different zones. Some dashboards also set a **now delay** in the time picker so that `now` really means `now-1m`; this hides the last, still-incomplete collection window, which otherwise shows as a fake dip at the right edge of every graph. ## What a panel receives per query For each query Grafana sends: the time range, a **max data points** value, an **interval**, and the query text itself. The panel's Query options expose the knobs: - **Max data points** — defaults to the panel's width in pixels. Requesting more points than the panel has pixels buys nothing but transfer, parse and render cost. - **Min interval** — a floor on the step. Set it to the collection interval; asking for a finer step than the data was collected at produces gaps or interpolation, not detail. - **Relative time** — this panel uses its own window regardless of the dashboard ("always show the last hour"). - **Time shift** — this panel uses the dashboard window shifted back by an offset ("same six hours, one week ago"). - **Cache timeout / query caching** where supported, plus a hidden-time-info toggle so viewers can see that a panel is not on the dashboard's range. ## How the interval is computed ``` interval = max( timeRange / maxDataPoints , minInterval , dataSourceMinStep ) then rounded up to a friendly unit: 1s 2s 5s 10s 15s 30s 1m 5m ... ``` That number is what `$__interval` expands to inside the query text; `$__interval_ms` is the same quantity in milliseconds for backends that want a number. `$__from` and `$__to` expand to the epoch-millisecond bounds (with formatting options for date-typed backends), and relational data sources add time-filter and time-bucket macros that expand into engine-appropriate SQL using the same bounds. The consequence is that the same saved query returns different resolutions at different zoom levels — which is the point. Zoom out to 30 days and the step widens, so the backend aggregates rather than shipping millions of points. This is also why a query with a *hard-coded* step is a bug: it ignores zoom, and at wide ranges it will either overload the backend or be silently truncated by a server-side point limit. ## Why $__rate_interval exists Rate-style functions need at least two samples inside their window, and in practice several, to survive a missed scrape. If `$__interval` happens to land at or below the collection interval — easy at narrow time ranges on a wide panel — a rate over `$__interval` sees one sample or none and produces gaps. `$__rate_interval` fixes this by widening the window to approximately `max($__interval + scrapeInterval, 4 × scrapeInterval)`, where the scrape interval comes from the data source's configured minimum step. The rule of thumb: use `$__rate_interval` for rate-like windows and `$__interval` for grouping/bucketing. ## Refresh The refresh picker re-executes **every** panel on the dashboard (subject to lazy loading — panels far below the fold and panels inside collapsed rows are not queried until they become visible). Facts worth stating: - Load scales as panels × viewers ÷ refresh interval. A 40-panel dashboard on a 5-second refresh open on six wall displays is 48 queries per second, forever. - Grafana enforces a server-side **minimum refresh interval** so a user cannot pick 1s on a shared instance; the allowed list is configurable, and a dashboard can be saved with a default. - A refresh interval finer than the data's collection interval only re-fetches the same points. Match the refresh to the collection rate at best. - Changing the time range re-runs queries too; so does hitting the manual refresh control, which is the correct default for expensive dashboards. - A refresh value can be carried in the URL, which is how kiosk-mode wall dashboards are configured. ## Putting it together in an interview The strongest answer connects the three: the range decides *what window*, max data points and min interval decide *at what resolution*, refresh decides *how often you pay for it*. Every performance conversation about a Grafana dashboard is some combination of those three plus the panel count.
- A graph shows a dip at the right-hand edge every time you look at it. What is the likely cause and the fix?The newest bucket is still filling: the collection window that covers 'now' is incomplete, so its aggregate is lower than the ones before it. The standard fixes are to set a now delay in the dashboard time picker so 'now' means a minute or so ago, or to shift the panel's window slightly. Increasing the refresh rate makes it worse, not better.
- Someone hard-codes a five-second step into a query instead of using the interval macro. What breaks?The query stops responding to zoom. At a narrow range it is merely redundant; at a thirty-day range it asks for hundreds of thousands of points per series, which is slow, may hit a server-side point limit and can be rejected outright, and renders far more points than the panel has pixels. Using the interval macro lets the step widen with the range, which is what keeps wide views cheap.
saying these in an interview costs you the question
- Thinking each panel has its own independent time range by default
- Setting refresh finer than the collection interval and expecting more detail
- Hard-coding a step instead of using the interval macro
- Sharing a relative-time dashboard link during an incident and assuming everyone sees the same window
- Confusing $__interval with $__rate_interval and then blaming the backend for gappy rate graphs