Data Incident Postmortem: [Incident title]
Blameless postmortem for a data incident: bad, late or missing data, a schema break, silent duplication, or personal data exposed in an analytics environment. It records detection, the blast radius traced through lineage (OpenLineage specification 2-0-2), the consumers and decisions affected, restatement and backfill, data contract and service level breaches, the personal data notification check (GDPR Articles 33 and 34, handled through the Incident Response Plan), root cause, data quality rule gaps and actions. Severity uses SEV1 to SEV4 from the Incident Severity Matrix. Replace every [bracketed] value and every row marked Example. The notification section is a documentation format, not legal advice.
Document control
| Field | Value |
|---|
| Document ID | [DIP-YYYY-NNN] (Example: DIP-2026-014) |
| Incident title | [Short description] (Example: Duplicate payment records overstated net revenue for 2026-10-13 and 2026-10-14) |
| Incident type | [Wrong data / Late data / Missing data / Schema break / Silent duplication / Personal data exposure / Other] |
| Severity at declaration | [SEV1 / SEV2 / SEV3 / SEV4] |
| Peak severity | [SEV1 / SEV2 / SEV3 / SEV4] per Incident Severity Matrix (ops/incident-severity-matrix) |
| Data products and datasets | [Products and output ports] |
| Incident window (first bad data to corrected data) | [YYYY-MM-DD HH:MM to YYYY-MM-DD HH:MM UTC] |
| Incident commander | [@incident-commander] |
| Postmortem owner | [@postmortem-owner] |
| Version | [0.1] |
| Status | [Draft / In review / Approved / Actions complete] |
| Owner | [@data-product-owner] |
| Approvers/reviewers | [@data-owner], [@data-quality-lead], [@dpo] (for section 9), [@consumer-representatives] |
| Last updated | YYYY-MM-DD |
| Classification | [Internal / Confidential] |
| Linked records | [Incident ticket], [Security incident ID if any], [Change requests], [Service postmortem if any] |
Approvals
| Role | Name | Decision | Date |
|---|
| Data product owner | [@name] | [Approve / Approve with conditions / Reject] | YYYY-MM-DD |
| Data quality lead | [@name] | [Decision] | YYYY-MM-DD |
| Data protection officer (section 9) | [@name] | [Decision] | YYYY-MM-DD |
| Main consumer representative | [@name] | [Decision] | YYYY-MM-DD |
Revision history
| Version | Date | Author | Change summary |
|---|
| 0.1 | YYYY-MM-DD | [@name] | First draft during the incident |
| 0.2 | YYYY-MM-DD | [@name] | Example: Added lineage analysis and restatement results |
| 1.0 | YYYY-MM-DD | [@name] | Example: Approved after the review meeting |
Contents
1. Summary
Example: A payments change-data-capture connector replayed about 45 minutes of payment events at each of two restarts, on 2026-10-13 and 2026-10-14. The staging model for payments had no uniqueness test, so duplicated payment rows fanned out in the join that computes order net amounts. For business dates 2026-10-13 and 2026-10-14, net revenue in the Orders data product was overstated by EUR 412,600 (3.10%), and the inflated figures reached the finance daily flash report and the marketing bid-optimisation export for about 42 hours. The daily reconciliation rule failed on both mornings, but its alert went to a ticket queue and nobody acted until a finance analyst noticed the mismatch. We deduplicated payments in staging, backfilled the two partitions and issued a restated flash report. The main follow-up is a Critical uniqueness rule in staging and paging on reconciliation failures for Tier 1 data.
2. Classification and scope
2.1 Type and severity
| Item | Value |
|---|
| Incident type | Example: Silent duplication (wrong values, no failure signal from the pipeline) |
| Data tier (Data Quality Standard section 4) | Example: Tier 1 |
| Severity at declaration | Example: SEV2 |
| Peak severity | Example: SEV2 (unchanged) |
| Severity rationale | Example: Data impact criterion (matrix section 4.3): corrupted figures reached an internal financial report and an automated spending decision, but the source events were intact and the corruption was recoverable with no loss, which is SEV2. Security criterion (section 4.4) not met: no unauthorised access to personal or confidential data. Customer impact criterion (section 4.1) not met: no customer journey affected |
| Crisis flag (if your matrix uses one) | Example: Not set |
2.2 Data-specific severity guidance
Classify with the Incident Severity Matrix (ops/incident-severity-matrix); each criterion is evaluated on its own and the most severe result wins. The examples below show how data incidents map to the matrix criteria. Wrong figures already used in external, regulatory or investor reporting may justify the crisis flag of the matrix on top of the level; record that decision in section 2.1. Raise the level as soon as a criterion is met, never lower it to avoid an obligation, and record both the level at declaration and the peak.
| Severity | Data incident examples (Example) |
|---|
| SEV1 | Confirmed unauthorised access to personal or confidential data, whatever the number of records (security criterion, matrix section 4.4); data lost or corrupted beyond what can be recovered within the recovery point objective, or writes silently dropped (data criterion, section 4.3) |
| SEV2 | Wrong or missing Tier 1 data used in internal or automated decisions, recoverable from intact sources (section 4.3); personal data possibly visible to unauthorised users while access is not yet confirmed (credible indication under investigation, section 4.4) |
| SEV3 | Tier 2 data late or partly wrong with a workaround; a schema break caught before consumers used the data |
| SEV4 | A failed rule or anomaly with no consumer impact yet; a near miss |
2.3 When to use which postmortem
| Situation | Template |
|---|
| Data wrong, late, missing, duplicated or exposed | This template |
| Application or service outage or degradation | Postmortem (dev/postmortem) |
| Security incident (with or without personal data) | Incident Response Plan (compliance/incident-response-plan) for handling; this template for the data restatement |
| Model or AI system behaved unexpectedly | AI incident templates in this library |
3. Impact
3.1 Data impact
| Dimension | Value | Source |
|---|
| Datasets with wrong data | Example: stg_payments_api__payments, int_orders__lines_joined_to_payments, fct_orders, orders (output port), orders_daily_agg | Lineage query (section 6) |
| Partitions affected | Example: Business dates 2026-10-13 and 2026-10-14 | Reconciliation results |
| Records affected | Example: 11,310 of 364,800 orders (3.10%) had an inflated net_amount | Comparison with corrected backfill |
| Size of error | Example: Net revenue overstated by EUR 412,600 on a true total of EUR 13,310,000 (3.10%) | Reconciliation with order service ledger |
| Exposure duration | Example: 42 h 20 min (first wrong publish 2026-10-14 02:45 to corrected publish 2026-10-15 21:05 UTC) | Publish logs |
| Data lost | Example: None; source events were intact | Source audit |
| Personal data involved | Example: No exposure; see section 9 | DPO decision |
Per business date (Example):
| Business date | Orders | Orders affected | True net revenue (EUR) | Overstatement (EUR) | Overstatement |
|---|
| 2026-10-13 | 182,100 | 5,640 | 6,640,000 | 205,900 | 3.10% |
| 2026-10-14 | 182,700 | 5,670 | 6,670,000 | 206,700 | 3.10% |
| Total | 364,800 | 11,310 | 13,310,000 | 412,600 | 3.10% |
3.2 Consumers and decisions affected
| Consumer | Use | Decision or action taken on bad data | Consequence | Corrective action |
|---|
| Finance (Example) | Daily flash report (net revenue) | Flash report of 2026-10-14 and 2026-10-15 sent to leadership | Leadership saw revenue 3.1% above actual | Restated report issued 2026-10-16 |
| Marketing (Example) | Bid-optimisation export from orders_daily_agg | Automated bidding raised budgets for two days | Estimated overspend EUR 18,400 | Budgets reset; export paused until restatement |
| Data science (Example) | Demand forecast features | Weekly retrain scheduled 2026-10-19 | None: backfill completed before retrain | Retrain checked against corrected data |
| Executive metric MET-REV-001 "Net revenue" (Example) | Semantic model SEM-ORD-001 (orders_semantic) | Viewed in dashboards | No external use | Dashboard banner during incident |
| [Consumer] | [Use] | [Decision] | [Consequence] | [Action] |
3.3 Contract and service level breaches
| Commitment | Source | Breach | Measure |
|---|
| DQ-ORD-004 accuracy (difference at most 0.1%) (Example) | Data Contract for orders (data/data-contract) | Yes, 2 daily partitions | Difference 3.10% on both days |
| Freshness at most 60 minutes (Example) | Same contract, service levels | No | Freshness met throughout |
| Correctness SLO: 99% of daily partitions pass all Critical and Major rules over 90 days (Example) | Orders data product SLOs | Yes | Budget 0.9 partitions; 2 failed; 222% of budget consumed |
| [Commitment] | [Source] | [Yes / No] | [Measure] |
Error budget arithmetic (Example): 90 partitions x (1 - 0.99) = 0.9 failing partitions allowed; 2 / 0.9 = 2.22, so 222% of the budget was consumed and the error budget policy freezes non-reliability changes to the Orders product until it recovers.
4. Timeline
| Time (UTC) | Event | Key moment |
|---|
| 2026-10-13 22:40 (Example) | Payments CDC connector restarted after broker maintenance; offsets reset to an earlier position and about 45 minutes of payment events (about 3.1% of the day's payments) are replayed | Defect introduced |
| 2026-10-14 02:00 | Nightly dbt build runs; staging payments now hold duplicate payment_id values; no test fails | |
| 2026-10-14 02:45 | orders and orders_daily_agg published with inflated net_amount for 2026-10-13 | Start of consumer impact |
| 2026-10-14 06:00 | DQ-ORD-004 reconciliation fails (difference 3.10%); rule is Major, so the day is flagged provisional and a ticket is created in the producer queue | First automated signal |
| 2026-10-14 07:30 | Finance flash report generated; the report does not display the provisional flag | |
| 2026-10-14 08:00 | Marketing bid export reads orders_daily_agg and raises budgets | |
| 2026-10-14 21:55 | Connector restarts again during a deploy; second replay | |
| 2026-10-15 02:45 | Inflated data published for 2026-10-14 | |
| 2026-10-15 06:00 | DQ-ORD-004 fails again; second ticket created | |
| 2026-10-15 13:20 | Finance analyst reports that net revenue does not match payment provider settlements | First human notice |
| 2026-10-15 13:35 | Incident declared SEV2; incident commander assigned | Detection (declared) |
| 2026-10-15 13:50 | Lineage query lists downstream datasets and consumers (section 6) | |
| 2026-10-15 14:10 | Decision to pause the marketing bid export (section 7.2) | |
| 2026-10-15 14:30 | Marketing export paused; banners on dashboards; flash report marked provisional | Mitigation |
| 2026-10-15 16:10 | Root cause found: duplicate payment_id rows in staging | |
| 2026-10-15 18:40 | Fix merged: deduplication on payment_id in staging plus a uniqueness test (later catalogued as DQ-ORD-007) | |
| 2026-10-15 21:05 | Backfill of two partitions published through write-audit-publish; reconciliation difference 0.02% | End of consumer impact |
| 2026-10-16 09:00 | Restated flash report issued; incident resolved | All-clear |
4.1 Key durations
| Measure | Calculation | Value (Example) |
|---|
| Time to first automated signal | 2026-10-13 22:40 to 2026-10-14 06:00 | 7 h 20 min |
| Time to declare (from defect) | 2026-10-13 22:40 to 2026-10-15 13:35 | 38 h 55 min |
| Time to mitigate (from declaration) | 13:35 to 14:30 | 55 min |
| Time to correct data (from declaration) | 13:35 to 21:05 | 7 h 30 min |
| Consumer exposure | 2026-10-14 02:45 to 2026-10-15 21:05 | 42 h 20 min |
5. Detection
| Question | Answer (Example) |
|---|
| Who or what detected it? | A finance analyst comparing revenue with payment provider settlements (consumer-detected) |
| Did any rule or monitor fire? | Yes: DQ-ORD-004 failed twice; volume and freshness monitors did not fire because row counts and timing were normal |
| Where did the signal go? | To the producer ticket queue, because Major rules create tickets; nobody watches that queue outside business hours and the tickets were not triaged within the target |
| Why did prevention not stop it? | No uniqueness rule on payment_id in staging; the join assumed one payment per order line |
| Could a consumer have seen the provisional flag? | No: the flash report and the bid export ignore the flag |
Detection category: consumer-detected after automated signal ignored. This counts against the "consumer-detected defects" metric of the Data Quality Standard (data/data-quality-standard).
6. Blast radius and lineage
6.1 Method
Lineage is collected as OpenLineage run events (specification 2-0-2) from the orchestrator and from dbt. Each run event names the job, the run, and its input and output datasets with facets such as the schema; input datasets can also carry data quality assertion results. To find the blast radius:
- Start from the dataset where the defect entered (here
stg_payments_api__payments).
- Walk output datasets of every job that read it, recursively, for runs between the defect time and the fix.
- For each downstream dataset, list the runs that wrote affected partitions, and the readers (jobs, dashboards, exports) of those partitions.
- Confirm each reader with its owner; record readers that lineage missed and add them to lineage collection (action item).
6.2 Lineage graph
The graph below combines the lineage events for the incident window with consumers confirmed by owners (Example). The marketing bid export was not in lineage and was found only by asking owners (section 6.3).
6.3 Affected assets
| Asset | Type | Owner | Affected partitions | Consumed bad data? | Confirmed with |
|---|
orders (Example) | Output port | [@orders-owner] | 2026-10-13, 2026-10-14 | Yes | Lineage and query logs |
orders_daily_agg (Example) | Aggregate | [@orders-owner] | Same | Yes | Lineage |
| Finance flash report (Example) | Report | [@finance-bi] | Same | Yes | Report owner |
| Marketing bid export (Example) | Reverse ETL export | [@marketing-ops] | Same | Yes | Not in lineage; found by asking (action A5) |
| Demand forecast features (Example) | Feature table | [@ds-lead] | Same | No (not yet retrained) | Feature owner |
| [Asset] | [Type] | [@owner] | [Partitions] | [Yes / No] | [Evidence] |
7. Response, containment and communication
7.1 Containment options considered
| Option | Chosen? | Reason (Example) |
|---|
Roll back orders to the last good snapshot | No | Would also remove correct data for later dates and break incremental state |
| Pause downstream exports | Yes | Stops new automated decisions on bad data immediately |
| Mark partitions provisional and add dashboard banners | Yes | Consumers keep access with a visible warning |
| Hide affected partitions | No | Finance needed the rest of the day's data for operations |
7.2 Key decisions
| Time | Decision | Made by | Rationale (Example) |
|---|
| 14:10 | Pause the marketing bid export | Incident commander with marketing owner | Prevent further automated overspend |
| 16:30 | Fix in staging and backfill, rather than patch the aggregate | Data owner | Fixing at the source keeps all downstream assets consistent |
7.3 Communication
| Time | Audience | Channel | Message summary |
|---|
| 14:30 (Example) | All consumers of Orders | Data status page and consumers channel | Incident declared; 2026-10-13 and 2026-10-14 revenue overstated; do not use for decisions; next update 17:00 |
| 17:00 (Example) | Same | Same | Cause found; corrected data expected by 22:00 |
| 2026-10-16 09:00 (Example) | Leadership and finance | Email from finance BI lead | Restated flash report with the size of the correction |
Use Incident Communication (dev/incident-communication) for message templates and cadence.
8. Restatement and backfill
8.1 Backfill plan
| Step | Action | Validation | Status (Example) |
|---|
| 1 | Deploy deduplication on payment_id in staging | Uniqueness test passes on full history | Done |
| 2 | Rebuild staging and intermediate models for 2026-10-13 and 2026-10-14 | Row counts match source ledger | Done |
| 3 | Rebuild fct_orders, orders, orders_daily_agg for both dates on an unpublished branch | DQ-ORD-001 to DQ-ORD-006 pass; reconciliation difference 0.02% | Done |
| 4 | Publish atomically (write-audit-publish) | Snapshot ID recorded | Done |
| 5 | Refresh semantic model caches, dashboards and the bid export | Spot checks by owners | Done |
| 6 | Notify consumers of corrected data | Message sent | Done |
8.2 Restatement of decisions and reports
| Item | Restated? | How | Owner |
|---|
| Finance flash reports 2026-10-14 and 2026-10-15 (Example) | Yes | Restated report with correction table | [@finance-bi] |
| Marketing budgets (Example) | Partly | Budgets reset; overspend recorded, not recoverable | [@marketing-ops] |
| [Item] | [Yes / No / Partly] | [How] | [@owner] |
9. Personal data and notification check
Personal data exposure in analytics happens more often than teams expect: email addresses in event properties, free text in search terms, identifiers in URLs, or a restricted table copied into an open sandbox. Whenever personal data may be involved, hand the breach assessment to the process in the Incident Response Plan (compliance/incident-response-plan) immediately; this postmortem records the outcome and does not replace that process.
Apply these points when you assess the incident (check the consolidated text and your own legal advice):
- Is it a personal data breach (Art. 4(12))? A personal data breach is a breach of security leading to the accidental or unlawful destruction, loss, alteration, unauthorised disclosure of, or access to, personal data. It covers confidentiality (data seen by people who should not see it), integrity (data altered) and availability (data lost or unreachable).
- Confidentiality in analytics is a breach. Personal data that becomes visible to people without authorisation is a personal data breach, also when the viewers are employees, when the data sits in an internal analytics zone, and when the identifiers are pseudonymous. Pseudonymised data remains personal data. Do not argue such an exposure away; record it as a breach and assess the risk.
- Assess the risk, then decide on notification (Art. 33). The controller notifies the competent supervisory authority without undue delay and, where feasible, within 72 hours of becoming aware of the breach, unless the breach is unlikely to result in a risk to people's rights and freedoms. Pseudonymisation, encryption, a short exposure to a small group of trusted staff, and prompt deletion can lower the risk; they are factors in the assessment, not reasons to skip it. A processor informs the controller without undue delay.
- Communicate to people when the risk is high (Art. 34). When the breach is likely to result in a high risk to the people concerned, the controller also tells them without undue delay, unless an Art. 34(3) condition applies.
- Document every breach (Art. 33(5)). Record the facts, effects and remedial action in the internal breach register, whether or not it is notified. Record a "not a breach" decision and its reasoning too.
- Other regimes. Other jurisdictions and sector rules have their own triggers and deadlines; the Incident Response Plan lists them.
| Question | Answer (Example) |
|---|
| Did affected datasets contain personal data? | Yes, pseudonymous customer_id in orders (Confidential, flags PD and PSEUDO in the Orders data contract) |
| Was personal data disclosed to or accessed by anyone without authorisation (confidentiality)? | No: access logs show only the authorised analytics, finance and marketing roles read the affected partitions; the bid export sent aggregates by campaign, without customer_id |
| Was personal data destroyed, lost or made unavailable (availability)? | No: source payment and order records were intact throughout |
| Was personal data altered (integrity)? | Derived order amounts linked to pseudonymous customers were wrong in analytics tables because of a processing defect; source records and identifiers were unchanged |
| Is this a personal data breach under Art. 4(12)? | No, per DPO assessment at 2026-10-15 15:00 UTC: no breach of security (no unauthorised access, no loss, source records intact); the wrong derived values are a data accuracy issue (Art. 5(1)(d)), corrected by the backfill of section 8 |
| Risk to people's rights and freedoms | Not applicable as no breach; the DPO noted that no decision about an individual customer used the affected values |
| GDPR Art. 33 notification to the supervisory authority required? | No (not a breach) |
| GDPR Art. 34 communication to data subjects required? | No (not a breach) |
| Recorded in the internal breach register (Art. 33(5))? | Assessment and reasoning recorded in the breach register as "assessed, not a breach", linked to the incident ticket |
| Other notifications (contracts, regulators, partners) | None required |
| Decided by | [@dpo] |
If the answer to the confidentiality question had been yes (for example the marketing export had carried customer_id to an advertising partner without a legal basis), the incident would be a personal data breach and SEV1 under the security criterion of the Incident Severity Matrix. Complete the risk assessment below in that case and follow the Incident Response Plan for the notification decision.
| Risk factor | Assessment (fill when a breach is confirmed) |
|---|
| Categories and approximate number of people and records | [Number of data subjects, record count, data categories] |
| Type of breach | [Confidentiality / Integrity / Availability] |
| Ease of identification | [Direct identifiers / pseudonymous with key held separately / other] |
| Severity of consequences for people | [For example financial loss, discrimination, loss of control over data] |
| Recipients and their trustworthiness | [Internal role, processor, third party, public] |
| Mitigation already applied | [Deletion confirmed by recipient, access revoked, keys rotated] |
| Risk level and decision | [Unlikely to result in a risk / Risk: notify authority / High risk: notify authority and people] |
| Time of awareness and notification deadline | [YYYY-MM-DD HH:MM UTC, plus 72 hours] |
If the analytics data is listed in the Record of Processing Activities (compliance/gdpr-ropa), check whether the incident shows that the record is out of date.
10. Root cause analysis
10.1 Causal chain
- Example: Broker maintenance caused the payments CDC connector to restart and resume from an earlier offset (trigger).
- The connector delivers at-least-once; replayed events were appended to the raw payments table.
- The staging model selected all raw rows without deduplicating on
payment_id.
- The intermediate model joined order lines to payments assuming at most one payment per line, so duplicates multiplied amounts.
fct_orders summed the joined amounts, overstating net_amount for affected orders while order_id stayed unique, so DQ-ORD-001 passed.
- DQ-ORD-004 detected the difference, but its Major severity routed the alert to an unwatched queue, and downstream consumers ignored the provisional flag.
10.2 Five whys
| Why? | Answer (Example) |
|---|
| Why was revenue overstated? | Payment amounts were counted twice for 11,310 orders |
| Why were they counted twice? | Staging held duplicate payment rows after a replay |
| Why did staging hold duplicates? | The model assumed exactly-once delivery and had no uniqueness test |
| Why was there no test? | At the time, the dbt project standard required primary key tests on marts only, not on staging models |
| Why did the reconciliation failure not stop publication? | Accuracy rules were rated Major for all tiers, and Major does not block or page |
10.3 Contributing factors
| Factor | Category (Data Quality Standard section 11.4) | Evidence |
|---|
| At-least-once ingestion without downstream deduplication (Example) | Ingestion | Connector documentation and raw table history |
| Join grain assumption not tested (Example) | Transformation logic | Model code review |
| Reconciliation rated Major on Tier 1 data (Example) | Rule gap | Data contract rule DQ-ORD-004 |
| Provisional flag not shown by consumers (Example) | Definition | Report and export code |
| Reverse ETL export missing from lineage (Example) | Orchestration and platform | Section 6.3 |
11. Data quality rule gaps
| Gap ID | Gap | Type | Fix | Enforcement point | Owner |
|---|
| GAP-01 (Example) | No uniqueness rule on payment_id in staging | Missing rule | Add DQ-ORD-007, Critical, block downstream | EP3 transformation | [@payments-steward] |
| GAP-02 (Example) | No fan-out check on the order line to payment join | Missing rule | Add a row count consistency test before and after the join | EP3 | [@orders-steward] |
| GAP-03 (Example) | Reconciliation rated Major on Tier 1 | Wrong severity | Raise DQ-ORD-004 to Critical for Tier 1; block publish above 0.5% | EP4 publish gate | [@finance-steward] |
| GAP-04 (Example) | Reconciliation alerts routed to an unwatched queue | Alert routing | Page producer on-call for Tier 1 Critical failures, per Alerting Policy (ops/alerting-policy) | EP5 | [@orders-custodian] |
| GAP-05 (Example) | Distribution monitor absent on net_amount per order | Missing monitor | Monitor mean and 99th percentile of net_amount per order | EP5 | [@orders-custodian] |
| [GAP-nn] | [Gap] | [Type] | [Fix] | [EPn] | [@owner] |
12. What went well and what did not
- Lineage events let the team list most downstream assets within 15 minutes of declaration.
- Write-audit-publish made the backfill safe and atomic; consumers never saw a half-corrected state.
- Finance raised the issue in the shared channel instead of correcting figures locally.
Did not go well (Example):
- The first of two automated signals went unanswered for 31 h 35 min (2026-10-14 06:00 to declaration at 2026-10-15 13:35).
- The bid export was missing from lineage, so marketing was informed late.
- The provisional flag existed but no consumer used it.
Where we were lucky (Example):
- The weekly forecast retrain was scheduled after the backfill.
- The month-end close was not in the incident window.
13. Action items
| ID | Action | Type | Owner | Due | Ticket | Status |
|---|
| A1 (Example) | Add DQ-ORD-007 uniqueness on staging payments (GAP-01) | Prevent | [@payments-steward] | YYYY-MM-DD | [link] | Done |
| A2 (Example) | Require primary key tests on all staging models in the dbt Project Standard (data/dbt-project-standard, section 6, minimum tests per layer) | Prevent | [@analytics-eng-lead] | YYYY-MM-DD | [link] | Done |
| A3 (Example) | Raise DQ-ORD-004 to Critical for Tier 1 and update the Orders data contract (GAP-03) | Detect | [@finance-steward] | YYYY-MM-DD | [link] | Open |
| A4 (Example) | Route Tier 1 Critical failures to the on-call pager (GAP-04) | Detect | [@orders-custodian] | YYYY-MM-DD | [link] | Open |
| A5 (Example) | Emit lineage events from the reverse ETL tool | Detect | [@data-platform-lead] | YYYY-MM-DD | [link] | Open |
| A6 (Example) | Make the flash report and the bid export refuse provisional partitions | Mitigate | [@finance-bi], [@marketing-ops] | YYYY-MM-DD | [link] | Open |
| A7 (Example) | Configure the CDC connector to keep committed offsets across maintenance restarts | Prevent | [@platform-eng] | YYYY-MM-DD | [link] | Open |
| [An] | [Action] | [Prevent / Detect / Mitigate / Process] | [@owner] | YYYY-MM-DD | [link] | [Status] |
Track completion in the quarterly data quality review (Data Quality Standard section 13.3). The postmortem status moves to "Actions complete" when every Prevent and Detect action is done.
14. Glossary and references
14.1 Glossary
| Term | Meaning |
|---|
| Backfill | Rebuilding historical partitions of a dataset with corrected logic or data |
| Blast radius | All datasets, reports, exports, models and decisions downstream of a defect |
| CDC | Change data capture: streaming row changes from a source database |
| Fan-out | A join that multiplies rows because the join key is not unique on one side |
| Restatement | Reissuing a report or figure with corrected values and an explanation |
| Silent duplication | Duplicate records that cause no pipeline failure and look plausible |
| Write-audit-publish | Load to an unexposed location, run checks, then publish atomically |
| Personal data breach | A security breach leading to accidental or unlawful destruction, loss, alteration, unauthorised disclosure of or access to personal data (GDPR Art. 4(12), paraphrased) |
14.2 References
| Reference | Version or date checked | Use |
|---|
| OpenLineage specification 2-0-2, openlineage.io/spec/2-0-2/OpenLineage.json | Project release 1.54.0, 2026-10-13, Apache-2.0 | Run, job, dataset and facet model; run event types for lineage-based impact analysis |
| Bitol Open Data Contract Standard (ODCS) v3.2.0, github.com/bitol-io/open-data-contract-standard | Released 2026-09-08, Apache-2.0 | Quality rule and service-level concepts referenced in section 3.3 |
| Regulation (EU) 2016/679 (GDPR), Articles 4(12), 33 and 34, eur-lex.europa.eu/eli/reg/2016/679/oj | Checked 2026-10-24 | Breach definition and notification triggers (paraphrased) |
Incident Severity Matrix (ops/incident-severity-matrix) | [Version] | SEV1 to SEV4 classification |
Incident Response Plan (compliance/incident-response-plan) | [Version] | Breach assessment and notification process |
Standard and licence note
Based on the OpenLineage specification 2-0-2 (Apache-2.0, openlineage.io) for lineage concepts, the Bitol Open Data Contract Standard (ODCS) v3.2.0 (Apache-2.0, github.com/bitol-io/open-data-contract-standard) for contract and service-level concepts, and Articles 4(12), 33 and 34 of Regulation (EU) 2016/679 (GDPR), paraphrased in original words. This is a documentation format, not legal advice. Severity levels follow this library's Incident Severity Matrix. The structure and text are original, written for this collection; Corvid Commerce and the incident are fictional. Check the current official versions and the consolidated legal text before use. Template licence: MIT.