Three Data Studio objects execute on schedules: dataset refreshes, data model builds and archive runs. All three share one scheduling mechanism and one logging discipline — a cron expression on the object, a background scheduler that queues due work, and an append-only run history per object — so learning the rules once covers all of them. This page is the reference for those shared rules and the per-object specifics.
The three scheduled jobs
| Job | Scheduled by | What a run does | History |
|---|---|---|---|
| Dataset refresh | The dataset's Refresh schedule, plus its Full reload schedule when Incremental | Validates the dataset, regenerates its SQL and writes its table by its refresh type: in full, its newest periods, or a new snapshot | Refresh History tab of the dataset workspace |
| Data model build | The model's Refresh schedule, plus its Full rebuild schedule | Validates the model, regenerates its SQL and writes its table in full or for its trailing window of days, then (by default) refreshes the datasets and graphs built on it | Build History tab of the model workspace |
| Archive run | The archive rule's Schedule | Resolves the cutoff, copies qualifying rows to the warehouse, verifies the copy, then marks them deleted in the operational database | History action on the rule's row |
Each also runs on demand — Compile on a dataset, Build on a model, Run on an archive rule. Manual and scheduled runs execute the same code and land in the same history; the difference is only what triggered them and who is notified. A dataset or model on an incremental refresh also offers a full rebuild on demand — Full reload on a dataset, a full rebuild on a model.
Runs can wait for capacity
Data model builds and dataset compiles run on your organization's share of the analytics warehouse, so a due run is not always started at once. It is admitted in order, checking your organization's licence, its limit on runs in parallel, its rolling daily capacity allowance and, if one is set, its build window (a UTC time range that holds scheduled and large runs; a small run started by hand is not held). A run that cannot start yet stays Pending with the reason, for example Daily capacity exhausted — resumes ~HH:MM, and is looked at again a few minutes later. The Build queue page (/analytics/builds) shows queued and running builds with their wait reasons, and your capacity used and remaining over the last 24 hours. A dataset compiled as part of a model's build is not admitted separately.
Cron rules
Schedules are standard five-field cron expressions — minute, hour, day of month, month, day of week — for example 0 3 * * * (daily at 03:00) or 0 2 * * 0 (Sundays at 02:00). Four rules matter in practice:
- Evaluation is in UTC. There is no per-organization time zone on schedules; convert your intended local time to UTC when writing the expression. The screens do the conversion back for you: as you type, the schedule field shows the next run in your organization's default time zone with UTC alongside — for example Next: Sun 1 Nov, 08:30 IST (03:00 UTC) for
0 3 * * 0in an Indian organization. - A blank schedule means manual-only. Nothing runs automatically; the object still works via its manual action. This is a legitimate configuration, not a misconfiguration.
- An invalid expression cannot be saved. The schedule field checks the expression with the scheduler's own parser as you type, and saving rejects anything the scheduler could not run — a malformed expression, a six-field (seconds-first) one, or one that matches no date such as
0 0 30 2 *— with the reason under the field. This applies to dataset, data model, data graph and archive rule schedules however they are saved (dialog, API or the Setup Copilot). A schedule saved before this check existed keeps working as before: the scheduler still skips it silently, the list and Overview show Invalid schedule — never runs in red, and you meet the error the next time you edit the schedule itself. - The scheduler evaluates every minute. A due occurrence is picked up within about a minute of its time; the run itself then queues behind whatever else is executing.
When a scheduled run fires
Every minute the scheduler evaluates each eligible object and queues a run when a cron occurrence has passed since the object's last successful run. The eligibility gates, per object:
- Datasets — Active, with a non-blank schedule.
- Data models — Active and Published, with a non-blank schedule. A draft model never builds on schedule, whatever its cron says. (Published is a toggle in the model's Edit dialog — there is no separate publish action.)
- Archive rules — Active, with a non-blank schedule.
Three consequences of the "last successful run" baseline are worth knowing:
- Failed runs do not advance it. A failing object is retried at each subsequent occurrence rather than dropped, so a persistent failure shows up as a run of failures in history, not as an absence.
- Nothing is replayed. An object with no successful run yet starts from a two-minute look-back at the moment it becomes eligible, so a schedule you set for an hour ago does not fire retroactively — the first run is the next occurrence. After downtime, a long-inactive period or a run of failures, the object runs once and is current again; missed occurrences are not executed one by one (for archive rules that single run covers the whole accumulated backlog).
- Duplicates are skipped. If a queued occurrence is processed after a later run already succeeded, it is discarded. Archive rules go further and record the skip (see below).
Run records and statuses
Every run that starts — manual or scheduled, successful or not — appends a history entry with started and completed times, status, row count, duration and an error message on failure. Statuses as the surfaces label them:
| Surface | Statuses |
|---|---|
| Dataset refresh history | Queued, Running, Success, Failed, Canceled |
| Data model build history | Pending, Running, Succeeded, Failed, Canceled |
| Archive run history | Queued, Running, Success, Failed, Canceled, Skipped Duplicate |
Skipped Duplicate is unique to archiving: a run whose window — same rule, cutoff, target, date field and condition — was already covered by a running or successful run records itself as skipped, referencing the run it duplicated, instead of re-archiving. Histories show the most recent 50 runs; they are append-only, so the trail of an incident survives its resolution.
Who is notified
| Job | On failure | On recovery |
|---|---|---|
| Dataset refresh (scheduled) | The dataset's creator receives an in-app notification and an email with the error — once, on the first failure after a success | One in-app notification and email when the next scheduled refresh succeeds again |
| Data model build (scheduled) | The model's creator, the same way | The same way |
| Archive run (scheduled) | The rule's owner, the same way — the message says nothing was retired | The same way |
| Any manual run | Nothing beyond the toast and the history row | — |
The notifications are deliberately quiet: they mark changes of state, not occurrences, so an object that has been broken since Tuesday does not mail its owner every hour. They also only fire for runs that start — an object that never becomes due (inactive, blank or invalid schedule) sends nothing.
Reading the history well
- Row count is the run's own output: rows materialized for refreshes and builds, rows moved for archive runs. Zero is a normal value when nothing qualified, not an error.
- Error message carries the underlying reason on failure — a SQL error in an expression, a missing field, warehouse connectivity. It is the first thing to read, and usually the last.
- A validation failure leaves no run at all for datasets and models — the SQL is only generated and executed once validation passes. History silence plus a validation error in the UI means the definition, not the execution, is what needs fixing. A scheduled run that fails validation is recorded as a notification to the dataset's creator but not retried until the next occurrence.
- Incremental runs say when they fell back. An incremental dataset refresh or model build that rebuilt everything instead (no table yet, no time dimension or incremental column, changed columns) records the reason on its run. A Full run's duration tracks total data volume, so a rebuild time that grows steadily is telling you about data growth — worth knowing before, not after, the schedule window gets tight, and a reason to consider Incremental.
Common questions
Why did my scheduled job never run?
Answer in order of likelihood: the object is inactive; the schedule is blank; the cron expression is invalid (only possible for a schedule saved before save-time validation — the list and Overview show Invalid schedule — never runs); or — for data models only — the model is not published. All four produce the same symptom, an empty or unmoving history and a Last refresh of Never run in the dataset list, and all four are visible on the object's Overview in under a minute. A fifth, rarer cause: the analytics warehouse was unreachable at every occurrence — that one does leave failed runs in history.
Do failed runs stop the schedule?
No. The schedule measures itself against the last successful run, so an object that failed will be tried again at the next occurrence rather than abandoned. That is the safe default — transient warehouse connectivity heals itself — but it means a definitional error (a bad expression, a renamed field) produces repeated failures until someone fixes the definition or deactivates the object. A history full of identical failures is a fix-me signal, not a wait-it-out signal.
What time zone do schedules use?
UTC, always. An expression like 0 3 * * * runs at 03:00 UTC regardless of where your organization or its users are — 08:30 IST. Write schedules in UTC deliberately — especially for archive rules and heavy dataset rebuilds you want inside a quiet window, since "quiet at 3 a.m." is only true in the time zone you meant. The next-run text under the field, in your organization's time zone, is the quickest check that you converted correctly.
Schedules stay in UTC on purpose. Every existing schedule, every analytics template and every seed pack is written in UTC, and the build window and capacity allowance are UTC too; evaluating some schedules in a local zone would silently move all of them, and daylight-saving zones would skip or double a run twice a year.
Can I see when the next run is due?
Yes. The Datasets list has a Next refresh column, Data models a Next build column and Archive rules a Next run column; the dataset and model Overview show the next refresh (and the next full reload or rebuild, when one is scheduled). Each is the next occurrence of the cron in your organization's default time zone with UTC alongside. An inactive object shows Paused (inactive), a draft data model Paused (draft — not published), an expression the scheduler cannot run Invalid schedule — never runs, and a blank schedule a dash. The time is when the run becomes due — a build can still wait in the Build queue after that, for capacity or the build window.
