---
name: report-automation
description: >
  Set up recurring reports that arrive reliably and get read: choose the cadence from the decision they serve, make the data refresh finish before the report sends, target the right recipients, handle failures with alerts and retries, and retire reports no one opens. Covers scheduled versus data-driven and conditional delivery, decoupling refresh from render from send, staggering jobs, bursting one report per audience, service accounts and row-level security, report fatigue, and refresh cost and rate limits. Use it when someone says "automate this report", "schedule a weekly report", "email this dashboard every Monday", "set up recurring reports", "our scheduled report is stale or failing", or "stop the report spam". Do NOT use it to design a live dashboard (see dashboard-design), write the narrative content of a report (see data-storytelling), choose which metrics to include (see metric-selection), or build the data pipeline that loads the warehouse (that is data engineering).
license: Free to use and adapt under CC BY 4.0, with credit to Afeez Adebayo. Link afeezadebayo.com, https://www.linkedin.com/in/afeez-adebayo/ and this skill's page at https://afeezadebayo.com/skills-md/data/dashboards-reporting/report-automation/.
---

# Report automation

## When to use this, and when not to

Use this skill when the job is to make a report happen on a schedule without someone rebuilding it by hand each time: a weekly performance email, a monthly board pack, a daily operational summary, a report burst to many recipients with each seeing their own slice. The triggers are a request to automate or schedule a report, email a dashboard on a cadence, set up recurring delivery, or a complaint that a scheduled report is stale, failing, or that people are drowning in report emails.

Do not use it to design the live dashboard people open themselves, which is `dashboard-design`, to write the narrative and recommendation inside a report, which is `data-storytelling`, or to choose which metrics the report should carry, which is `metric-selection`. Building the pipeline that loads the warehouse is data engineering, upstream of this skill. This skill assumes the report content exists and is correct, and makes its delivery dependable and timely.

The core idea: an automated report is a small production system, not a one-off send. It has inputs that can be late, a job that can fail, recipients whose needs change, and a cost in compute and attention. Treat it that way. The two failures that destroy trust are a report that arrives before its data finished refreshing, so the numbers are wrong, and a report that fails silently, so no one notices until a stakeholder does. Most of this skill is about preventing those two.

## Inputs the agent must have before starting

1. **The decision the report drives, and its cadence.** What someone does with it and how often that decision is made. A report read to act today is daily; one reviewed against targets is weekly or monthly. The decision sets the cadence, not habit.
2. **The recipients and how they differ.** Who receives it, and whether they all see the same thing or each needs their own filtered slice (a region, a team, an account). This decides a single send versus a burst.
3. **The data source and its refresh timing.** When the underlying data updates, how long a refresh takes, and its time zone. This is the input that most often breaks a report, so pin it down.
4. **The delivery channel and format.** Email, a chat channel, a shared drive, or an embedded link, and the format (PDF, image, spreadsheet, a link to the live view). Each has different size and security limits.
5. **The tool doing the sending.** The BI tool, spreadsheet, script or orchestration tool, because its scheduling model, limits and failure behaviour set what is possible (the mechanics live in the appendix).
6. **Who owns it, and when it should stop.** A named owner and a review or expiry date, so the report does not outlive its usefulness.

If the report sends to other people, that is an action on their behalf. Set it up in a disabled or test state first, send a sample to the owner, and get explicit confirmation before enabling the live schedule.

## The workflow, step by step

### 1. Confirm a report is the right tool

A scheduled report suits information reviewed on a rhythm. If the audience needs to dig into and filter, build a live dashboard instead (`dashboard-design`). If they only need to know when a threshold is crossed, build an alert, not a recurring report, because a daily email that says "nothing changed" trains people to ignore it. Decision rule: if the usual content of the report is "no action needed", switch it to an exception-only alert.

### 2. Set the cadence from the decision, not from habit

Match the schedule to how often the decision is actually made: daily for operational monitoring, weekly or monthly for performance tracking, quarterly for strategic review (coupler.io, "Report scheduling"). Decision rule: do not send more often than the audience acts; a daily report for a weekly decision is six wasted emails that erode attention. Pick a send time tied to when the decision is made (a Monday 8 am report for a Monday planning meeting), not an arbitrary midnight.

### 3. Make the refresh finish before the report sends

This is the rule that prevents wrong numbers. Schedule the data refresh to complete before any dependent send, with a buffer: a 7:00 am send after a 6:30 am refresh, not both at 7:00 (ChristianSteven, "Tableau scheduled-reporting best practices"). Better still, make delivery data-driven where the tool supports it, so the report sends only after the refresh succeeds rather than at a fixed clock time. In Tableau this is the "When Data Refreshes" subscription rather than "On Selected Schedule" (Tableau Server Help, "Create a Subscription"). Decision rule: never schedule a send at the same time as its refresh; either leave a buffer or trigger the send on refresh completion.

### 4. Decouple refresh, render and delivery

Keep the three stages separate: the data refresh, the rendering of the report, and the send. If they are welded together, one slow extract stalls every queued report (ChristianSteven). Separating them lets a failed refresh stop the send (so stale data is never delivered) without taking down unrelated reports, and lets you retry one stage without redoing all three.

### 5. Stagger jobs so they do not collide

Do not run every refresh and send at the top of the hour. Stagger them, for example at 6:45, 7:00 and 7:15, so a burst of jobs does not exhaust the tool's capacity or the refresh window (ChristianSteven). Run heavy monthly jobs overnight to keep business-hour capacity free. Respect the tool's refresh limits: shared or entry tiers cap scheduled refreshes per day, higher tiers allow many more, so check the limit before promising an hourly report on a tier that cannot do it (see appendix, and verify the current limits for your tool).

### 6. Target recipients, and burst rather than copy

If different people need different slices, use one report filtered per audience segment (bursting) rather than hand-built copies, so a region's lead gets only their region (ChristianSteven). Tie the distribution list to a directory group rather than a list of static email addresses, so the report follows role changes instead of mailing people who have left (ChristianSteven). Decision rule: if you are maintaining more than one near-identical copy of a report by hand, replace them with one bursted report.

### 7. Send only what is worth sending (conditional delivery)

Where the tool allows it, send conditionally: skip the email when the view is empty or nothing crossed a threshold, so recipients get a report only when there is something to see. Tableau offers "Don't send if view is empty" for exactly this (Tableau Server Help). Decision rule: for any report whose point is exceptions, make delivery conditional so a quiet period is silent, not a stream of empty reports.

### 8. Handle failure loudly, not silently

Treat a scheduled report as a production job (ChristianSteven). A failed refresh or send must raise an alert to the owner immediately, not wait for a stakeholder to notice stale numbers. Route the alert to where the owner will see it (a chat channel, a pager, an email that is itself monitored). Set a retry on transient failures, and know the tool's own failure behaviour: Tableau suspends a subscription after more than five consecutive failures, so a long-broken report stops sending entirely and must be resumed (Tableau Server Help). Decision rule: every automated report has an owner who is alerted on failure; a report no one is alerted about is a report that will silently rot.

### 9. Secure the delivery

Run production schedules under a service account, not a named person's login, so the report does not break when that person changes role or leaves (ChristianSteven). Apply row-level security at the source so each recipient sees only the data they are entitled to, especially in a burst. Send a link to a permissioned live view rather than a fully loaded attachment when the data is sensitive, and never put credentials or secrets in the report body or the schedule configuration. Decision rule: if a report contains personal or restricted data, prefer a permissioned link over an open attachment, and confirm the recipient list is entitled to every row.

### 10. Name an owner and a retirement trigger

Every automated report gets a named owner, a review cadence, and a condition under which it stops. Audit schedules regularly and retire any report with no engagement, for example one not opened by any recipient in 90 days (ChristianSteven). Unused scheduled reports cost compute, clutter inboxes, and erode trust in the ones that matter. Decision rule: a report that no recipient has opened in a quarter is paused and its owner asked whether to keep it.

### 11. Verify, then enable from a safe state

Build the schedule disabled or pointing at a test recipient, run one cycle, and confirm the data is current, the right people are targeted, the format renders, and a forced failure actually raises an alert. Only then enable the live schedule, and only after the owner has confirmed. Run the result against the quality bar below.

## Worked example, end to end

A revenue team asks to "automate the weekly sales report and send it to the regional managers every Monday." The quick version schedules the workbook to email at 7:00 am Monday to a static list, with its data extract also refreshing at 7:00 am. Two weeks in, managers get Monday numbers that are actually the previous Tuesday's, because the extract had not finished, and one manager who left still receives a region's full figures.

Done as a production job instead. Cadence: weekly, sent 8:00 am Monday to land before the 9:00 am regional call. Refresh: the extract is scheduled for 6:30 am, and the subscription is set to "When Data Refreshes" so it only sends once the refresh succeeds, with a fixed-time fallback disabled until the refresh is proven reliable. Decoupling: refresh, render and send are separate jobs, staggered so this report's refresh at 6:30 does not collide with the finance refresh at 6:30. Recipients: a single bursted report filtered by region, tied to the "Regional managers" directory group, with row-level security so each manager sees only their region. Failure handling: a failed refresh posts to the revenue team's ops channel immediately, with a retry, and the owner is named in the schedule. Security: it runs under a reporting service account, and sends a link to the permissioned view rather than a full attachment. Retirement: reviewed quarterly, paused if a region's manager has not opened it in 90 days. It is enabled only after a test send to the owner confirmed current data and correct targeting.

## Templates you can use verbatim

**Report automation spec (fill in before enabling any schedule):**

```
Decision + cadence:   what it drives, how often the decision is made, send time
Recipients:           one list or bursted per segment; directory group or static
Data source:          where from, refresh duration, time zone
Refresh-before-send:  buffer time, or data-driven trigger (send on refresh success)
Delivery:             channel, format, link vs attachment
Failure plan:         who is alerted, where, retry policy, tool suspend behaviour
Security:             service account, row-level security, link vs attachment
Owner + retirement:   owner, review cadence, stop condition (e.g. 90 days unopened)
```

**Pre-enable checklist:** refresh completes before send (buffer or data-driven); recipients correct and entitled; format renders; a forced failure raises an alert; schedule starts disabled or test-only; owner has confirmed; conditional send set if the report is exception-based.

**Failure-alert line (adapt per tool):** "Report [name] failed at [stage: refresh/render/send] at [time]. Owner [name] notified via [channel]. Last successful run [time]. Recipients were not sent stale data."

## Failure modes and anti-patterns

1. **Report sends before refresh finishes.** Send and refresh scheduled at the same time, so recipients get stale numbers. Spot it when the report's figures lag a cycle. Fix: leave a refresh buffer or switch to data-driven "send on refresh success" (ChristianSteven; Tableau).
2. **Silent failure.** A broken refresh or send that no one is alerted to, noticed only when a stakeholder flags wrong or missing numbers. Spot it from gaps in delivery history. Fix: alert the owner on every failure, add retries, and know the tool's suspend-after-N-failures behaviour (ChristianSteven; Tableau).
3. **Report fatigue.** A daily report that usually says "nothing changed", so recipients filter it to a folder and miss the day it matters. Spot it from low open rates. Fix: make it exception-based with conditional delivery, or switch to an alert (coupler.io; Tableau "Don't send if view is empty").
4. **Static recipient lists and hand-built copies.** People who left still receive sensitive reports, and one report is maintained as five near-identical copies. Spot it from bounced or ex-employee recipients. Fix: burst one report by segment, tied to directory groups (ChristianSteven).
5. **Owned by a person's login, no owner on the schedule.** The report breaks when that person changes role, and no one is responsible for it. Spot it when a schedule fails after someone leaves. Fix: run under a service account and name an owner and review cadence (ChristianSteven).

## Quality bar

- The cadence matches how often the decision is made, and the send time is tied to when it is used.
- The data refresh completes before the report sends, by a buffer or a data-driven trigger; send and refresh are never scheduled at the same instant.
- Refresh, render and delivery are decoupled, and jobs are staggered rather than all at the top of the hour.
- Recipients are correct and entitled; differing slices are handled by a bursted report tied to a directory group, not hand-built copies.
- A failure at any stage alerts a named owner immediately, with a retry policy, and the tool's suspend-after-failures behaviour is known.
- Production schedules run under a service account, with row-level security, and sensitive data goes as a permissioned link rather than an open attachment.
- Exception-based reports use conditional delivery so quiet periods are silent.
- The report has an owner, a review cadence and a retirement trigger, and was enabled from a disabled or test state only after a confirmed test send.

## Data handling and safety

Automated reports move data to people on a schedule, which makes a mis-targeted report a repeating leak rather than a one-off mistake. Confirm every recipient is entitled to every row before enabling a schedule, apply row-level security at the source, and prefer a permissioned link to the live view over a fully loaded attachment for anything personal or restricted. Never put credentials, tokens or secrets in a report body, a subject line, or a schedule's configuration. Enabling a recurring send to other people is an irreversible action on their behalf that then repeats, so set it up disabled, send a test to the owner, and get explicit confirmation before it goes live; the same applies to changing the recipient list of a live report. Never fabricate the contents of a report to fill a scheduled slot: if the data did not refresh, the honest outcome is a held send and an alert, not a report of last cycle's numbers presented as current. When a report informs decisions about money, health, legal standing or employment, make sure its stated data freshness and any caveats travel with it, so a late or partial refresh is visible rather than hidden.

## Appendix: tool-specific notes (verify before relying on these)

- **Tableau:** subscriptions email a PNG or PDF snapshot; use "When Data Refreshes" for data-driven delivery and "On Selected Schedule" for fixed times, "Don't send if view is empty" for conditional sends, and note that a subscription is suspended after more than five consecutive failures and must be resumed. Data Management adds data-quality warnings in the email. Verify current behaviour in your version.
- **Power BI:** use subscriptions for scheduled snapshots and data alerts for thresholds; scheduled refreshes are capped per day on shared and Pro capacity and allow many more on Premium, Premium Per User or Fabric capacity, so check the current limit for your licence before promising a frequent report, and set the dataset refresh to complete before the subscription time.
- **Looker / Looker Studio:** use scheduled deliveries with filters for bursting, and conditional delivery where available; define the metric once in the model so the scheduled report and the live dashboard agree.
- **Spreadsheets and scripts (Google Sheets, Apps Script, cron, Airflow, dbt):** when you own the schedule, make the send depend on the refresh job succeeding rather than a fixed clock time, log every run, alert on failure, and keep credentials in a secret store, not in the script.

## Sources

- ChristianSteven Software, "Tableau scheduled-reporting best practices": schedule the refresh to complete before any dependent send with a buffer, decouple refresh, rendering and distribution, stagger jobs rather than running them all at once, treat scheduled reports as production applications with runbooks and failure alerting, burst one filtered report per segment, tie distribution to directory groups, use service accounts, run quarterly audits and retire reports with no engagement in 90 days. (Vendor of a reporting-orchestration tool, so its case for external tooling reflects that; the practices are general.) Verified 3 November 2026.
- Tableau Server Help, "Create a Subscription to a View or Workbook": the "On Selected Schedule" and "When Data Refreshes" delivery options, the "Don't send if view is empty" conditional option, subscribing groups, and suspension after more than five consecutive failures with a Resume Subscription action. Verified 3 November 2026.
- coupler.io, "Report scheduling": choose the interval from business need (daily for real-time monitoring, weekly or monthly for performance tracking), set the refresh window and time zone so data is current before delivery, enable a notification on an unsuccessful run, and check scheduled solutions regularly rather than assuming a built-in schedule fits. Verified 3 November 2026.
- Amplitude, "Leading vs lagging indicators", and general reporting-cadence practice: match reporting frequency to how often the underlying decision is made, which informs the cadence rule here. Verified 3 November 2026.
