# Data Quality Report — Sample

**This is an illustrative example.** The pipelines, thresholds and results are invented to
show the shape of a report someone will actually act on. Copy the structure; your thresholds
must come from your own data.

A quality report has one job: say whether today's numbers can be relied on, and if not,
exactly which ones. Everything below is arranged so that a person who reads only the first
table knows the answer.

---

## Data quality — 2026-08-04

| | |
|---|---|
| Pipelines | 9 |
| Runs | 14 (9 daily, 5 hourly) |
| Overall | **1 pipeline failed closed · 1 degraded · 7 clean** |
| Reported to | Data platform team and the finance definition owner |

## 1. Can today's numbers be relied on?

| Domain | Status | If not, what is affected |
|---|---|---|
| Orders | ✅ Clean | — |
| Revenue | ⚠️ **Yesterday's data** | Revenue dashboards show 2026-08-03. Not wrong; one day behind. |
| Customers | ✅ Clean | — |
| Inventory | ⚠️ Degraded | Loaded, but 4.1% of rows missing a category |
| Web analytics | ✅ Clean | — |

**Nothing published today is wrong.** One domain is stale and one is incomplete, and both are
labelled as such on the dashboards.

## 2. The five checks

| Pipeline | Freshness | Volume | Uniqueness | Nulls | Reconciliation |
|---|---|---|---|---|---|
| orders_daily | ✅ 02:14 | ✅ 48,201 | ✅ | ✅ | ✅ ±0.00% |
| revenue_daily | ❌ **not run** | — | — | — | — |
| customers_daily | ✅ 02:31 | ✅ 1,204 new | ✅ | ✅ | ✅ ±0.00% |
| inventory_daily | ✅ 03:02 | ✅ 88,410 | ✅ | ⚠️ **category 4.1%** | ✅ ±0.02% |
| web_events_hourly | ✅ 09:05 | ⚠️ low, in range | ✅ | ✅ | n/a |
| finance_extract | ✅ 04:00 | ✅ | ✅ | ✅ | ⚠️ **±0.31%** |

Thresholds, for reference: volume within ±25% of the 28-day median for the same weekday;
nulls above 1% in a normally-populated field; reconciliation beyond ±0.1% against the system
of record.

## 3. revenue_daily — failed closed, as designed

| | |
|---|---|
| Time | 02:45 |
| Trigger | Source extract contained 312 rows against a 28-day median of 44,900 |
| Check that caught it | Volume |
| Action taken | **Wrote nothing.** Previous day's output left in place. Exited non-zero. |
| Alert | Paged the on-call data engineer at 02:46 |
| Cause | Upstream export ran against a replica mid-resync |
| Fix | Upstream scheduling changed. Re-run scheduled for 06:00 tomorrow. |

**This is the report's most important entry, and it records a success.** The pipeline was
handed obviously wrong input and refused to publish it. Yesterday's revenue figure remained
on the dashboard with its date visible.

Consider the alternative. Had it written what it received, every revenue dashboard would have
shown a near-zero day. Someone would have escalated it as a commercial emergency, and the
first hour of the working day would have gone into explaining a number rather than fixing a
pipeline. **Stale data announces itself. Wrong data gets acted on.**

## 4. inventory_daily — degraded but published

4.1% of rows arrived with a null category, against a 0.2% baseline. Above the threshold, so
it is reported; not structurally broken, so it published with a marker.

Traced to a supplier feed that added a product line under a category code not in our mapping.
The rows are correct in every other field. Category-level inventory reporting is incomplete
for that supplier until the mapping is extended; total inventory is unaffected.

Publishing here was a judgement, and the judgement is recorded: the affected slice is
identifiable, everything else is intact, and the dashboard shows the gap rather than hiding
it. Had the nulls been spread unpredictably across suppliers, the same 4.1% would have been a
stop.

## 5. finance_extract — reconciliation drift

Totals differ from the source ledger by 0.31%, against a ±0.1% threshold. Third consecutive
day, and the gap is widening: 0.08%, 0.19%, 0.31%.

The direction is consistent, which rules out random loss. Current hypothesis is a timezone
boundary — transactions after 23:00 local landing in the following day's extract. Under
investigation; the pipeline continues to publish with the variance shown, because a known and
quantified 0.31% is more useful than no figure at all.

## 6. What no check can catch

Two open items are definition disputes, not data problems, and no automated check will ever
find them.

**"Active customer" has two definitions in use.** Marketing counts a purchase in 90 days;
finance counts any account not closed. Both dashboards are correct against their own
definition and they differ by roughly 40,000 people. The pipeline is not wrong. **This is the
most common cause of "our dashboards disagree", and it is resolved by naming an owner for the
definition, not by editing a query.**

**Refund timing is unspecified.** Refunds are currently applied to the original order date.
Whether they should reduce that day's revenue or the day the refund was issued has never been
written down. Both are defensible; only one can be true at a time.

Both are with the finance definition owner.

## 7. Actions

| Action | Owner | By |
|---|---|---|
| Re-run revenue_daily after the upstream fix | Data platform | Tomorrow 06:00 |
| Extend the supplier category mapping | Data platform | This week |
| Confirm or reject the timezone hypothesis on finance_extract | Data platform | 48 hours |
| Rule on the "active customer" definition | Finance definition owner | This week |
| Write down the refund timing rule | Finance definition owner | This week |

---

## Notes on using this format

**Lead with whether the numbers can be relied on.** Most readers need only that. The checks
underneath are for the people who have to act.

**Report a fail-closed event as a success.** If a stopped pipeline is written up as a failure,
the next engineer under pressure will make it publish through the error, and the report will
have caused exactly the incident it exists to prevent.

**Keep definition disputes in the report even though no check produces them.** They cause more
disagreement about numbers than every data defect above combined, and they are invisible in
any report generated purely from the pipeline.
