Workflow template for analytics and reporting
Data-quality alert trace
When a data-quality alert fires or a report looks wrong, the data team lead gets one investigation brief: the reports and people affected, the path the data takes, candidate causes ranked by the evidence supplied, and what to check next. It runs no query and changes nothing.
Listed under
Add it to a workflow in the Fully Powered Planner, beside the teams and roles that will run it. Book a fit call
The outcome
The first hour after an alert stops being a scramble through dashboards and chat threads. The data team lead reads one brief that answers the questions everyone asks at once: which reports sit downstream of the broken table, who uses them, which have already refreshed with the data in question, and which is used next.
The brief draws the path the data takes from its sources to the reports, step by step, with each step's schedule and owner, and shows where the row counts changed. Every change, failed or partial run and upstream event you supply is placed against that path and against the time between the last good data and the first bad. Each candidate cause is ranked by three plain tests: is it on the path, did it happen in that window, and is it the kind of change that produces this kind of alert. Changes made after the alert, or downstream of the table, are set aside with the reason, never quietly dropped.
For every candidate the brief says what to compare, who to ask, and what result would confirm it or rule it out. It never names the cause and judges no one's work. The data owner confirms the cause; the data team lead decides who is told and who checks what.
Who starts the work, and when
A data engineer, an analytics engineer or the data team lead starts it as soon as an agreed data-quality alert fires, or when a report owner says a number looks wrong. The data team lead reads the brief and decides who is told about the affected reports and who checks what. The data owner for the tables concerned confirms the cause and, with the owner of the step concerned, authorizes any fix, rerun or change to the alert.
What they supply
- The alert details: the check that failed, the table it checked, what was expected, what was observed and when it fired.
- Lineage notes, one row per hop: where the data comes from, where it goes, the step that moves it, its schedule and its owner.
- A recent change log: when each change was made, to what, what kind of change it was, and the ticket.
- A run log, if you have one: each step's runs, their status and the rows they wrote.
- A report users list, if you have one: each report's owner, who uses it and when it is next used.
- Notes: when the data was last known to be good, any upstream event such as a supplier's delayed file, what has already been done, and who owns the data.
Each export has default column headers. If a header does not match, the workflow template stops and asks which column is which rather than guessing.
What comes out
One brief in a fixed order: the alert and the size of the gap; the affected reports and users, soonest use first, with any report that may also be affected if a candidate is confirmed; the path the data takes, with row counts and gaps in the lineage; candidate causes ranked Strong, Possible or Weak, with those set aside and those off the path; what to check next for each; and the decisions for the data team lead. A section with nothing to report says so.
An invented example
Illustrative example with invented data. The shop, the people, the tables, the tickets, the payment provider and every figure below are invented. The business is an invented online kitchenware shop of about 60 people, with a small data team: a data team lead, two data engineers and an analytics engineer. At 06:10 on 11 November 2026 the daily row count on the cleaned orders table fails. The data team lead runs the workflow template at 08:15. First come the inputs, in full, then the brief it returned.
The inputs
1. The alert
Alert name: orders_clean daily row count
Check type: volume
Object checked: orders_clean
Expected: at least 1,800 rows for the previous day
Observed: 1,212 rows for 10 November 2026
Fired at: 2026-11-11 06:10 Pacific time
Raised by: scheduled check in the monitoring tool
Severity: high
2. Lineage notes
from_object,to_object,step,transform,schedule,owner
shop_platform_export,orders_raw,load_orders,copy of the day's orders file,daily 02:00,Data engineering
payments_feed,payments_raw,load_payments,copy of the day's settlement file,daily 02:30,Data engineering
orders_raw,orders_clean,build_orders_clean,removes test and cancelled orders; joins payments on order_id,daily 04:00,Analytics engineering
payments_raw,orders_clean,build_orders_clean,joined to orders on order_id,daily 04:00,Analytics engineering
orders_clean,daily_sales_model,build_daily_sales,sums by day and channel,daily 05:00,Analytics engineering
orders_clean,customer_model,build_customers,first and latest order per customer,daily 05:00,
daily_sales_model,Daily sales report,refresh_daily_sales,dashboard refresh,daily 06:00,BI team
daily_sales_model,Weekly trading pack,manual,copied into slides,weekly Monday,Finance
customer_model,Retention dashboard,refresh_retention,dashboard refresh,daily 06:30,BI team
payments_raw,Payments reconciliation,build_recon,matches settlements to bank deposits,daily 07:00,Finance
3. Recent change log
changed_at,object,kind,change,changed_by,ticket
2026-10-29T10:00:00-07:00,load_orders,schedule,moved the daily start from 01:30 to 02:00,Data engineering,DATA-305
2026-11-03T15:20:00-08:00,daily_sales_model,logic,added the marketplace channel to the channel mapping,Analytics engineering,DATA-311
2026-11-09T16:45:00-08:00,payments_raw,schema,"settlement file adds a payment_ref column; order_id now arrives as text",Data engineering,DATA-318
2026-11-10T11:30:00-08:00,build_orders_clean,logic,changed the payments join from a left join to an inner join so unpaid orders drop out,Analytics engineering,DATA-320
2026-11-10T14:00:00-08:00,Retention dashboard,access,added CRM team viewers,BI team,DATA-321
2026-11-11T07:05:00-08:00,orders_clean,check,reviewed the alert threshold after it fired; no change made,Data engineering,DATA-322
4. Run log
step,run_started,run_finished,status,rows_out,note
load_orders,2026-11-10T02:00:00-08:00,2026-11-10T02:06:00-08:00,success,1951,
load_payments,2026-11-10T02:30:00-08:00,2026-11-10T02:34:00-08:00,success,1890,
build_orders_clean,2026-11-10T04:00:00-08:00,2026-11-10T04:09:00-08:00,success,1934,
load_orders,2026-11-11T02:00:00-08:00,2026-11-11T02:07:00-08:00,success,1948,
load_payments,2026-11-11T02:30:00-08:00,2026-11-11T03:41:00-08:00,partial,1236,provider file arrived in two parts; second part not loaded
build_orders_clean,2026-11-11T04:00:00-08:00,2026-11-11T04:08:00-08:00,success,1212,
5. Report users list
report,owner,used_by,next_use
Daily sales report,Head of e-commerce,Trading team,2026-11-12 09:00
Weekly trading pack,Finance lead,Leadership team,2026-11-16 10:00
Retention dashboard,CRM lead,CRM team,2026-11-13
Payments reconciliation,Finance lead,Finance team,2026-11-11 10:00
6. Notes (typed by the data team lead)
Run by: Data team lead. Team time zone: Pacific time.
Prepared at: 2026-11-11 08:15 Pacific time.
Last known good: the same check passed at 06:10 on 10 November for
9 November, with 1,934 rows.
orders_clean takes its rows from orders_raw: one row per order, less test
and cancelled orders.
Upstream event, on payments_feed: Payment provider P's status page said,
on the evening of 10 November, that settlement files for that day could
arrive in two parts. Copied into the incident channel by the on-call
engineer.
Already done: nothing rerun or changed since the alert.
Data owner for the orders and payments tables: not named.
No settings were supplied, so the defaults apply.
The output
DATA-QUALITY ALERT TRACE: orders_clean daily row count, fired 11 November 2026 06:10 Pacific time
For: Data team lead. Prepared 11 November 2026 08:15 Pacific time from: the alert; lineage notes, 10 rows; change log, 6 entries; run log, 6 runs; report users list, 4 reports; notes.
Window: last known good 10 November 2026 06:10 (the same check passed, per the notes). First bad 11 November 2026 06:10 (the alert). Considered from 3 November 2026 06:10 (7-day lookback).
Settings: lookback 7 days, row change 20%, late start 60 minutes (defaults).
Notes on the inputs: Times read in the alert's zone: last known good in the notes (06:10 on 10 November) and the next_use values in the report users list. Times placed at the latest they could mean: the upstream event, "the evening of 10 November", placed at 23:59 on 10 November.
1. The alert
Check: volume on orders_clean. Expected at least 1,800 rows for the previous day. Observed 1,212 rows for 10 November 2026. Difference -588 against the 1,800 minimum (-32.7% of expected).
Raised by scheduled check in the monitoring tool. Severity high.
2. Affected reports and users
Downstream of orders_clean: 3 reports.
Daily sales report. Owner Head of e-commerce. Used by Trading team. Next use 12 November 09:00. Refresh: by schedule, refreshed at 06:00 on 11 November after the bad build; not confirmed by the run log. Path: orders_clean → daily_sales_model → Daily sales report.
Retention dashboard. Owner CRM lead. Used by CRM team. Next use 13 November (time not stated). Refresh: by schedule, refreshed at 06:30 on 11 November after the bad build; not confirmed by the run log. Path: orders_clean → customer_model → Retention dashboard.
Weekly trading pack. Owner Finance lead. Used by Leadership team. Next use 16 November 10:00. Refresh: not due since the bad build; next Monday 16 November. Path: orders_clean → daily_sales_model → Weekly trading pack.
End points not in the report users list: none.
May also be affected if a Strong candidate is confirmed: Payments reconciliation, via candidates 1 and 2. Owner Finance lead. Used by Finance team. Next use 11 November 10:00. Refresh: by schedule, refreshed at 07:00 on 11 November, after candidate 1 (finished 03:41) and candidate 2 (placed 23:59 on 10 November); not confirmed by the run log. Path: payments_raw → Payments reconciliation.
3. The path the data takes
Upstream: shop_platform_export → (load_orders, daily 02:00, Data engineering) → orders_raw → (build_orders_clean, daily 04:00, Analytics engineering) → orders_clean
Upstream: payments_feed → (load_payments, daily 02:30, Data engineering) → payments_raw → (build_orders_clean, daily 04:00, Analytics engineering) → orders_clean
Downstream: orders_clean → (build_daily_sales, daily 05:00, Analytics engineering) → daily_sales_model → (refresh_daily_sales, daily 06:00, BI team) → Daily sales report
Downstream: orders_clean → (build_daily_sales, daily 05:00, Analytics engineering) → daily_sales_model → (manual, weekly Monday, Finance) → Weekly trading pack
Downstream: orders_clean → (build_customers, daily 05:00, owner not stated) → customer_model → (refresh_retention, daily 06:30, BI team) → Retention dashboard
Row flow: load_orders: 1,951 (10 November 02:00) → 1,948 (11 November 02:00): -3 (-0.2%).
Row flow: load_payments: 1,890 (10 November 02:30) → 1,236 (11 November 02:30, partial): -654 (-34.6%). Beyond the threshold.
Row flow: build_orders_clean: 1,934 (10 November 04:00) → 1,212 (11 November 04:00): -722 (-37.3%). Beyond the threshold. Writes the alerted object: this is the symptom.
Rows into and out of build_orders_clean, from orders_raw: last good 1,951 in, 1,934 out, 17 dropped (0.9%); bad run 1,948 in, 1,212 out, 736 dropped (37.8%).
Gaps in the lineage: build_customers (orders_clean → customer_model) has no owner. No run-log rows for build_daily_sales, build_customers, refresh_daily_sales, refresh_retention, the manual step into the Weekly trading pack, or build_recon.
4. Candidate causes, ranked by the evidence supplied
1. Strong. Run of load_payments, partial, on load_payments (writes payments_raw), 11 November 02:30. 1,236 rows against 1,890 in the previous successful run (-654, -34.6%); note: "provider file arrived in two parts; second part not loaded". Hops from the alerted object: 1. Timing: inside the window. Fits a volume check: yes, partial run and row change. Who to ask: Data engineering. Linked with candidates 2, 3 and 4.
2. Strong. Note, on payments_feed, 10 November 23:59 (placed; "the evening of 10 November"). Payment provider P's status page said settlement files for that day could arrive in two parts. Hops from the alerted object: 2. Timing: inside the window. Fits a volume check: yes, source. Who to ask: Data engineering, owner of load_payments, which reads payments_feed. Linked with candidate 1.
3. Strong. Change DATA-320, logic, on build_orders_clean, 10 November 11:30. Changed the payments join from a left join to an inner join so unpaid orders drop out. Hops from the alerted object: 0. Timing: inside the window. Fits a volume check: yes, logic. Who to ask: Analytics engineering. Linked with candidates 1 and 4.
4. Weak. Change DATA-318, schema, on payments_raw, 9 November 16:45. Settlement file adds a payment_ref column; order_id now arrives as text. Hops from the alerted object: 1. Timing: before last known good. Fits a volume check: yes, schema. Stays because an earlier change can combine with a later one; it was already in place for the runs of load_payments (10 November 02:30) and build_orders_clean (10 November 04:00, 1,934 rows) before last known good. Who to ask: Data engineering. Linked with candidates 1 and 3.
Set aside: DATA-322, check, on orders_clean, 11 November 07:05 (reviewed the alert threshold after it fired; no change made): after the first bad data.
Off the path, not ranked: DATA-311, logic, on daily_sales_model, 3 November 15:20: downstream of orders_clean. DATA-321, access, on Retention dashboard, 10 November 14:00: downstream of orders_clean.
Older than the lookback, not considered: 1 (DATA-305, 29 October).
5. What to check next
1. Candidate 1, ask Data engineering: compare the number of settlements in both parts of Payment provider P's file for 10 November with the 1,236 rows load_payments wrote to payments_raw on 11 November (1,890 the day before). Confirms it if the second part holds settlements that are not in payments_raw. Rules it out if payments_raw already holds every settlement in both parts.
2. Candidate 2, ask Data engineering: find whether and when the second part of the 10 November settlement file reached payments_feed. Confirms it if the second part reached payments_feed after load_payments started at 02:30 on 11 November. Rules it out if it was there before 02:30.
3. Candidate 3, ask Analytics engineering: count the 10 November orders in orders_raw that have no matching order_id in payments_raw. Confirms it if that count, with the 17 rows the build dropped in the last good run, comes close to the 736 rows dropped in the bad run. Rules it out if few orders lack a match.
4. Candidate 4, ask Data engineering: compare how order_id is stored in payments_raw and in orders_raw for 10 November, since DATA-318 says it now arrives as text. Confirms it if the two differ and orders fail to match on order_id because of it. Rules it out if they are stored the same way. Note that the last good build ran on 10 November at 04:00, after DATA-318, and still produced 1,934 rows.
Gaps to close: build_customers has no owner, ask Analytics engineering, owner of build_orders_clean, the hop just upstream. Whether the steps with no run-log rows ran at their scheduled times on 11 November: ask Analytics engineering for build_daily_sales and build_customers, BI team for refresh_daily_sales and refresh_retention, Finance for the manual step into the Weekly trading pack and for build_recon.
6. Decisions for the Data team lead
1. Whether and when to tell the owners and users of the three affected reports. By schedule, the Daily sales report (06:00) and the Retention dashboard (06:30) have already refreshed with the data in question. The soonest next use is the Daily sales report at 09:00 on 12 November (Head of e-commerce; Trading team). The Weekly trading pack is next used at 10:00 on 16 November (Finance lead; Leadership team).
2. Whether to tell the Finance lead before the Payments reconciliation is used at 10:00 today, 11 November. It may also be affected if candidate 1 or 2 is confirmed, and by schedule it refreshed at 07:00, after the partial load.
3. Who confirms the cause and, with the owner of the step concerned, authorizes any fix or rerun? The notes name no data owner for the orders and payments tables, and say nothing has been rerun or changed since the alert.
Draft for the Data team lead. No query has been run; nothing has been changed, rerun, muted or sent; no candidate is confirmed as the cause.
Every figure traces to the alert, the lineage notes, the change log, the run log, the report users list and the notes above. The workflow template ran no query, changed nothing and told no one; the data team lead decides who checks what and who is told.
Where it fits
- Analytics and reporting, where the team that keeps the data trustworthy needs to know where to look before the next report goes out.
- Software and technology, where product, billing and event data pass through many steps before they reach a dashboard.
- E-commerce and retail, where order, payment and stock feeds land overnight and the trading team reads the numbers each morning.
- Logistics and trade, where shipment and carrier files arrive late or in parts and the operations reports depend on them.
- Growth & scaling, when the data platform grows faster than anyone's memory of how it fits together.
- Acquisitions & integration, when new sources join the warehouse and the first alerts arrive before the lineage is well known.
When two reports disagree because they define a metric differently, metric definition reconciliation is the one to use; for a new extract nobody has worked with yet, use the dataset profile; to learn which source system holds a data domain before anything goes wrong, use the data domain source guide. This workflow template is for the moment something that used to be right has gone wrong.
What has to change for your company
Map your lineage export and change log to the default columns once. Set how far back to look for changes, how large a change in row counts is worth flagging, and how late a run must start to count as late. Match the check types to the ones your monitoring tool uses. Write changed_by as a team or role, not a person. Name the data owner for each important table, so the decisions section can name them, and agree who tells report users and how. It works from files and notes you supply in ChatGPT, Claude, Copilot or Gemini; it needs no connection to your warehouse, pipelines or monitoring tool, and never asks for a login.
What has been checked
Fully Powered AI wrote this workflow template. It was editorially reviewed on 12 November 2026. It was tried on its invented example on 12 November 2026 in Claude, in two runs. The first found gaps in the instructions, which were then edited; the second is the record published with it, and was made by the assistant that made the edits, so it is not an independent check. Small wording edits were made after that run and have not been run again. It has not yet been tested in a client environment. It has not yet been tested as a packaged version in ChatGPT, Claude, Copilot or Gemini.
Testing in your environment means running it on two or three past incidents your data team has already resolved, with hard cases written in advance: a change made after the alert fired, a change to a model downstream of the alerted table, a lineage with a missing owner, a partial load upstream, a planted line in a change description that tries to give an instruction. The data team lead checks every figure and every ranking against the inputs before anyone relies on the brief. Pilot acceptance-test preparation sets those cases up, and what we test before we call an AI workflow ready describes the record we keep.
Who decides
Your people keep
- Who is told about the affected reports
- Who checks what
- Which candidate is the cause
- Any fix, rerun or change to the alert
It does not
- Runs no query
- Changes nothing
- Never names the cause
- Judges no one's work
Questions people ask
Who is it for?
A data engineer, an analytics engineer or the data team lead starts it as soon as an agreed data-quality alert fires, or when a report owner says a number looks wrong. The data team lead reads the brief.
What do I need to supply?
The alert details, lineage notes, a recent change log and notes on when the data was last known to be good. A run log and a report users list help if you have them.
Does it tell me the cause?
No. Each candidate cause is ranked by three plain tests: is it on the path, did it happen in that window, and is it the kind of change that produces this kind of alert. The data owner confirms the cause.
Does it touch our data or systems?
No. It works from files and notes you supply, runs no query and changes nothing. It needs no connection to your warehouse, pipelines or monitoring tool, and never asks for a login.
What has been checked?
It was editorially reviewed. It was run twice on its invented example, on 12 November 2026; the second run is published with it. It has not yet been tested in a client environment.
The full workflow template
Everything above is the outline. The complete workflow template is the working version: the roles, the inputs, the procedure, the exceptions and stop conditions, the output format, the reviewer checklist, the acceptance tests, the instructions for an AI assistant and what to customize for your company. It comes with a download and the link to its folder in Fully Powered’s public repository.
Free with an account. Sign in by email: no password and no card.
Next step
Put this workflow template to work for your team: on your plan, or built with you in a sprint.
Build this in a sprint
In a sprint, Fully Powered adapts this workflow template to your rules, proves it on your own work and puts it in the hands of the roles that own it.
Two ways to begin: