Core concepts
Schedules
Cadences and intervals, anchors and timezones, the precision you actually get, and what happens across a daylight-saving change.
A schedule answers one question: when does the scheduler re-run this dashboard's SQL? Everything else on this page is a consequence of how that question is stored and how the scheduler sweeps.
Cadences and intervals
A schedule is a time unit plus a multiplier, not a free-form expression. There is no cron string.
| Cadence | Multiplier allowed | Anchors it takes |
|---|---|---|
manual | none | none |
hourly | every 1, 2, 3, 4, 6, 8, or 12 hours | an optional hour |
daily | every 1 to 30 days | an optional hour, with a timezone |
weekly | every 1 to 4 weeks | a day of week, an hour and a timezone, all three or none |
monthly | every 1 to 12 months | a day of month, an hour and a timezone, all three or none |
manual means the dashboard only refreshes when a person or a tool asks it to.
It is not a degraded state: a dashboard with no schedule keeps its URL, its
versions, its thumbnail and its share link forever.
The hourly multipliers are the divisors of 24, so "every 5 hours" is refused. The reason is that a divisor keeps the daily hour grid clean and repeating: every 6 hours means the same four times every day, where every 5 hours would drift through the day and mean a different set of times each day.
Day of month is capped at 28. This is a deliberate clamp, not an oversight: you cannot ask for the 31st, because February would silently skip. If you need the end of the month, take the 28th.
Days of the week are numbered from 0 for Sunday.
Hourly is the fastest cadence. There is nothing below it: no every-15-minutes and no every-30-minutes.
Anchors and timezones
An anchor pins a cadence to a wall-clock moment: "daily at 09:00 in
America/New_York" rather than "every 24 hours from whenever this was armed".
Timezones are real IANA zone names. The anchor is interpreted in that zone, and the conversion to an absolute instant happens after the period arithmetic, which is what makes daylight saving behave correctly.
Without an anchor a cadence falls back to a plain interval from the last run: plus one day, plus seven days, plus thirty days. Note that unanchored monthly is a flat 30 days rather than a calendar month.
The precision you actually get
This is the part most likely to look like a bug, so it is worth stating plainly.
Dashies schedules to the minute you pick and starts the run within about half an hour of it. Usually much sooner.
Two things separate the nominal time from the actual one:
The sweep grid. The scheduler sweeps every 15 minutes, so a 09:00 run starts
at the first sweep at or after 09:00.
Anti-herd jitter. Each dashboard carries a stable offset of 0 to 14 minutes,
derived from its own id. It exists so a thousand dashboards all set to "daily
09:00" do not hit their warehouses simultaneously at 09:00. It is stable per
dashboard, so a given dashboard always drifts by the same amount.
The jitter lives only in the sweep's selection, never in the stored next-run
time. The "Next refresh" the web app shows you is the nominal instant, exactly
09:00, with no jitter baked in, so the displayed value and the stored value agree
byte for byte.
The practical reading: a dashboard ten minutes past its nominal time is healthy. The web app agrees with you about this and does not call a run late until it is more than 20 minutes past, precisely because a perfectly healthy dashboard is legitimately past its nominal time for up to fifteen minutes every cycle.
Every cadence uses the same grid.
If you need a number to the second, refresh on demand rather than tightening the cadence.
Daylight saving
For an anchored schedule, the period is added on the local date and only then converted to an absolute instant. That gives the behaviour you want:
- "Daily
09:00America/New_York" stays09:00local across a daylight-saving change. It does not drift to08:00or10:00. - On the transition day itself the real gap between two runs is 23 or 25 hours. That is the correct consequence of keeping the wall-clock time fixed, and it is accepted rather than corrected.
- A wall time that does not exist, in the spring-forward gap, or that happens twice, in the autumn repeat, is normalized silently. A run is never lost and never doubled.
An unanchored hourly schedule is unaffected, because it is defined on absolute instants rather than wall-clock times.
The web app's preview of the next run implements the same conversion, so the time it shows you and the time the run fires agree across a transition.
What happens when a run fails
A failed scheduled run is not abandoned and not retried immediately. The next attempt is pushed out by 5 minutes doubled per consecutive failure, capped at one full period of the dashboard's own cadence. So the retries go 5 minutes, 10, 20, 40, and so on, and a permanently broken daily dashboard settles into retrying about once a day rather than ninety-six times.
A success resets the counter and re-anchors the schedule normally.
A failing dashboard stays in the sweep. It is the backoff, not exclusion, that bounds the retry rate, which is why pausing is the way to stop retries rather than waiting for it to give up.
Two other outcomes are not failures and are labelled differently:
- No change. The run succeeded and the numbers came back identical. Your data genuinely did not move.
- Skipped. The write collided with a republish that landed between the read and the write. Nothing is lost; the next run picks up the new body.
Refreshing on demand
Three ways to ask for a refresh now: the web app, your AI tool, and a headless
HTTP endpoint. All three run the same recompute, all three require a paid plan,
and all three share one property worth relying on: an on-demand run never
pushes out the scheduled slot. Refreshing at 08:55 does not cancel the 09:00
run.
Two differences to know:
- All three work on a workspace dashboard. Refreshing rewrites the dashboard's data, so a team dashboard needs the same seat as republishing it and a view-only member is refused. The paid plan that matters there is the workspace's, not your own.
- The AI tool and the HTTP endpoint coalesce, for two different reasons.
They do not start a second run when one is already in flight for that
dashboard, whatever started it, including a scheduled run; and they do not
re-run when one finished within the last minute. A recent failed
attempt does not coalesce, because the data is still stale and reporting it
fresh would be a lie. Use
get_refresh_statusto see which of the two happened: it shows the live run, the surface that started it, and whether it is running the current version of the dashboard. - Nothing runs two refreshes of one dashboard at once, on any surface. The web app's "Refresh now" included: two clicks five seconds apart do not run twice, because the second one joins the first rather than starting beside it. Only the 60-second window above is surface-specific.
The receipt you get back is metadata only: how many rows, how long it took, whether the numbers changed. Never the data itself.
Next
Plans and what is gated, since most of this page needs one.