# BI Reporting Requirements Template

Seven fields for specifying a recurring report: what arrives, when, to whom, and what
happens when it breaks.

This is not the dashboard requirements template. A dashboard has to justify a decision. A
report has to justify a delivery, which means the fields you need are different ones.
If the thing you're specifying is a screen someone opens, use the
[dashboard requirements template](https://datawirefra.me/templates/dashboard-requirements-template.md)
instead.

Paste it into Google Docs, Notion, Confluence, or your wiki. Platform-agnostic: Power BI
subscriptions, Tableau subscriptions, Looker schedules, or a script and an SMTP server.

From [datawirefra.me/blog/bi-reporting-requirements](https://datawirefra.me/blog/bi-reporting-requirements)

---

## 1. Deliverable

What physically arrives, in the recipient's hands.

| Field | Value |
|-------|-------|
| Report name | |
| Format | _PDF / XLSX / CSV / email body / Teams or Slack post / link_ |
| Filename pattern | _e.g. `regional-sales_2026-09.xlsx`_ |
| Page or tab count | |
| Branding required | _logo, footer, confidentiality notice?_ |

Formats are not interchangeable. XLSX means someone will pivot it, so the grain matters more
than the formatting. PDF means nobody will pivot it, so the formatting matters more than the
grain. Email body means it gets read on a phone in about four seconds.

## 2. Recipients

| Field | Value |
|-------|-------|
| To | |
| CC | |
| Distribution mechanism | _named list / AD or Entra group / distribution list_ |
| **Accountable for correctness** | |
| Who to contact on failure | |

Name a person in the accountable row, not a team. A report nobody owns drifts quietly,
because noticing that it drifted is nobody's job.

If the distribution is a group rather than a list, write down who administers the group.
Reports outlive the people on their original recipient list.

## 3. Cadence and trigger

| Field | Value |
|-------|-------|
| Frequency | _daily / weekly / monthly / quarterly / on event_ |
| Exact timing | _e.g. Monday 07:00 America/Toronto_ |
| Timezone | |
| Trigger | _schedule, or a data condition_ |
| Depends on | _upstream job that must finish first_ |
| Behaviour on holidays | |

Write the timezone down explicitly. A "Monday 7am" report specified by someone in Toronto
and built by someone in Lisbon arrives on Sunday for half its audience.

The "depends on" row is the one that causes incidents. If the report can fire before the
warehouse load finishes, it will, and it'll send confidently wrong numbers.

## 4. Period and grain

| Field | Value |
|-------|-------|
| Period covered | _e.g. prior full calendar month_ |
| Row grain | _one row per what?_ |
| Comparison period | _prior period / prior year / target / none_ |
| Calendar | _calendar or fiscal, and when the fiscal year starts_ |
| Late-arriving data | _does the period get restated, or stay as sent?_ |

The last row matters more than it looks. If Tuesday's numbers change on Wednesday, either
your report contradicts itself over time or you freeze the period and accept it's slightly
stale. Pick one on purpose.

## 5. Metrics

| # | Metric | Exact calculation | Source | Rounding / units | Priority |
|---|--------|-------------------|--------|------------------|----------|
| 1 | | | | | |
| 2 | | | | | |
| 3 | | | | | |
| 4 | | | | | |
| 5 | | | | | |

A report is archived and forwarded, so its definitions behave differently from a
dashboard's. A dashboard can be corrected in place and everyone sees the corrected version.
Every copy of a report that has already been sent keeps the old arithmetic, sitting in
someone's inbox, being cited.

So write the calculation down here, and treat a change to it as a versioned change to the
report rather than a fix.

| Field | Value |
|-------|-------|
| Definition version | _v1_ |
| Changing a definition requires | _whose sign-off?_ |

## 6. Delivery and failure

| Field | Value |
|-------|-------|
| Channel | _email / SharePoint / SFTP / Teams / Slack_ |
| Permissions model | _who can open it once it's delivered?_ |
| Contains restricted data | _PII, salary, patient, financial pre-release?_ |
| Retention | _how long is it kept, and where?_ |
| **On failure** | _retry, alert someone, send nothing, or send late?_ |
| Who gets the failure alert | |

"Send nothing" and "send late" are different decisions with different consequences, and
somebody will make that decision at 6am under pressure if you don't make it now.

Silent failure is the worst option and the most common default. A report that stops arriving
is often noticed months later, if at all.

## 7. Review date

| Field | Value |
|-------|-------|
| Next review | _a date_ |
| Reviewed by | |
| Still needed if | _what would have to be true for this to stop?_ |

Reports accumulate. Most BI teams are running some that nobody has read in a year, and the
cost isn't just compute, it's that every one of them is a thing that can break loudly and
demand attention.

A date in this field is the cheapest way to make stopping a normal event rather than an
awkward conversation.

---

## Sign-off

- [ ] Format, filename and page count agreed
- [ ] A named person is accountable for correctness
- [ ] Timezone written down explicitly
- [ ] Upstream dependency identified
- [ ] Late-arriving data behaviour decided (restate or freeze)
- [ ] Every metric has an exact calculation and a source
- [ ] Failure behaviour chosen, and someone gets the alert
- [ ] Review date set

---

## The short version

If you only fill in three fields, fill in these:

1. **Accountable for correctness** — a name.
2. **Depends on** — the upstream job, so it can't fire early with wrong numbers.
3. **On failure** — because the alternative is silent failure, and silent failure is the
   default.

---

Building a screen someone opens rather than a file that arrives? That's a different
document: the [dashboard requirements template](https://datawirefra.me/templates/dashboard-requirements-template.md).
Free at [app.datawirefra.me](https://app.datawirefra.me).
