How to schedule SQL reports
Most teams already run a scheduler: cron on a server, Airflow, Dagster, Databricks Jobs or GitHub Actions. DRE doesn’t add another one. It keeps the schedule definitions next to the reports, shows when each one fires, and gives your scheduler one command to run, so a report runs on time and a rerun reproduces the original period.
1. Name the schedules next to the reports
schedules.yml lives in the project, in git. One report can have several schedules, each with its own variables, and a schedule can follow a group of reports by tag.
- name: flash_daily
report: sales_summary
cron: "0 7 * * *"
timezone: Australia/Sydney
vars: {period: day}
- name: close_monthly
report: sales_summary
cron: "0 6 1 * *"
timezone: Australia/Sydney
vars: {period: month}
- name: finance_daily
select: tag:finance
cron: "0 7 * * 1-5"
timezone: Australia/SydneyWhen many schedules share a timing, such as “the 1st of the month, 06:00 Sydney”, name it once intimings.yml (with holidays to skip) and refer to it from each schedule.
2. Check when they fire
dre schedule ls works out every firing in a window, so a reviewer can check that a cron expression and timezone mean what the author thinks, before it reaches production.
dre schedule ls # the next 5 firings of each schedule
dre schedule ls -s sales_summary --limit 10 # when does this report run?
dre schedule ls --output json # every firing in the next 35 days, with its command3. Let your scheduler run the command
Whatever the scheduler, the task is one command. Pass the instant the run was scheduled for in DRE_RUN_AT, so the report’s dates come from the schedule rather than the clock.
# min hour day month weekday
0 6 1 * * cd /srv/reports && DRE_RUN_AT="$(date -u +\%Y-\%m-\%dT\%H:00:00Z)" dre run --schedule close_monthly --target prodIn Airflow, Dagster or Databricks Jobs, run the same command as a task, usually right after the job that refreshes the tables (for example your dbt run), with the run’s logical time as DRE_RUN_AT. For a self-hosted setup that loads every firing into a database and runs what’s due, see the orchestration recipe, which DRE’s demo project tests against Postgres.
4. Rerun a period without editing anything
When someone asks for September again because late refunds came in, run the same schedule with September’s instant. The SQL, file names and email subjects render as they did on the day:
DRE_RUN_AT=2026-09-30T20:00:00Z dre run --schedule close_monthly --target prodEvery run records its schedule, variables and scheduled instant in run_results.json and its log, so you can see exactly what ran. (Reproducing the same numbers also needs the source data as it was, if it has changed since.)
Why not a scheduler built into the reporting tool?
Your scheduler already handles retries, alerts, dependencies and access control, and your team already watches it. Keeping report schedules there means reports run after the data they depend on, failures show up where the other failures do, and there is no second system to secure. DRE’s part is to make the schedule reviewable in git and the run reproducible.