---
title: "Data Pipeline Checklist: Accept Reliable Reporting"
canonical: https://wavect.io/software-development-guide/data-pipeline-acceptance-checklist/
language: en
description: "Accept the path from source records to a business decision, not just a dashboard screenshot. Use a worked order-and-refund example, freshness and replay tests, …"
image: "https://wavect.io/img/general/bak/open_graph_preview.jpg"
---

Data acceptance guide

# How do you know a data pipeline is ready for reporting?

Accept the path from source records to a business decision, not just a dashboard screenshot. Use a worked order-and-refund example, freshness and replay tests, access checks and a handover record to define reliable reporting.

Published: 2026-11-03 by Wavect

Short answer

A data pipeline is ready for reporting when agreed source records reconcile to defined metrics, late and repeated data behave predictably, stale results are visible, access restrictions hold and an owner can recover a failed run. Passing row counts alone does not prove the business number is correct.

Best for

- Teams buying a first warehouse or replacing manual reports
- Business owners who need to accept an analytical delivery

Outside this guide

- Sending operational records between live systems
- An audit opinion, legal retention advice or an ML model evaluation

// 01

## Compare the options

Choose thresholds from the business decision. These examples do not prescribe a universal service level.

| Check | Weak acceptance | Useful evidence |
| --- | --- | --- |
| Completeness | The job ran successfully | Expected source batch and record keys are accounted for |
| Correctness | The chart looks plausible | Named metric reconciles to agreed source evidence |
| Freshness | The dashboard loads | Source watermark and freshness status are visible |
| Replay | Retry button exists | Same input rerun does not change accepted totals |
| Access | Admin can open the report | Allowed and denied roles tested through report and export |
| Recovery | Backup job exists | A failed partition is recovered using documented steps |

// 02

## Where Wavect lands on this

### Start with the decision and its source of truth

A pipeline moves and transforms data into an analytical copy. A warehouse stores modeled data; a BI report presents it. A correct chart cannot repair a missing refund upstream. Before selecting tools, name the business decision, the metric owner and the authoritative system for each input. Operational order synchronization belongs to [API Integration](/services/api-integration/); analytical models and reporting belong to [Data Engineering](/services/data-engineering/).

Write a metric contract: grain, inclusion rules, event time, reporting timezone, currency, treatment of refunds and the point at which a period closes. For example, daily net collected revenue may differ from booked order value, recognized accounting revenue and payment-provider settlement. Do not give all four numbers the same label. Agree who resolves a discrepancy rather than letting a developer infer a finance policy.

### A worked order-and-refund acceptance example

Use a synthetic fixture with three paid orders: A for EUR 120, B for EUR 80 and C for EUR 50. One full refund of EUR 80 applies to B. Under the explicit definition ‘captured payments less completed refunds, in one currency, excluding fees and tax treatment’, the expected net collected amount is EUR 170: 120 + 80 + 50 - 80. This is a test example, not client data or an accounting rule.

Give each order and refund a stable source identifier. Deliver order A twice and replay the whole batch: the result must remain EUR 170, not EUR 290. Deliver B’s refund after the initial load: the accepted figure may first show EUR 250 with a clear provisional status, then EUR 170 after applying the agreed correction policy. The owner must approve whether historical days change or the adjustment appears in a later period. Those alternatives answer different business questions.

Now omit C, change a required field and supply an unknown currency. Record whether each case blocks publication, quarantines affected rows or displays a qualified result. There is no single correct policy for every report, but silent changes are an acceptance failure. Keep input identifiers, run ID, transformation version, expected value, actual value and the accepting role together. [Download the synthetic fixture and acceptance cases](/downloads/data-pipeline-acceptance-example.json) to adapt them.

### Choose checks that can detect the actual failure

Check key uniqueness, required values, referential integrity and allowed statuses near ingestion. Compare totals and counts by source, day and business unit, not just across a whole database where differences can cancel out. [dbt’s data-test documentation](https://docs.getdbt.com/reference/resource-properties/data-tests) describes executable assertions, while its [source documentation](https://docs.getdbt.com/docs/build/sources) provides the context for declaring upstream data. These are implementation examples, not a requirement to purchase dbt.

A fresh load timestamp is not proof of fresh business data. Expose both the pipeline run time and the latest source event included. A supplier could send yesterday’s file successfully today. Set the freshness target with the decision owner: a next-day management report and an intraday replenishment decision need different expectations. State which timezone and clock the target uses, and who is alerted when it is missed.

### Rehearse failure and recovery before acceptance

Interrupt a load after staging but before publication. The report should follow its agreed policy, for example retaining the last accepted snapshot with a visible stale-data warning. Rerun the same bounded input and verify no duplicated contribution. [Apache Airflow’s task guidance](https://airflow.apache.org/docs/apache-airflow/stable/best-practices.html) explains why retries need repeatable results and stable input partitions. Apply the principle even when orchestration is a simple scheduled script.

Keep recovery and correction separate: restoring yesterday’s warehouse does not reconstruct a refund that arrived today. Agree raw-data retention, replay boundaries, source availability and how downstream dashboards refresh after a corrected partition. Test recovery with representative data; a backup configuration screenshot is not a restore demonstration. Do not promise a recovery time until the relevant run has been measured.

### Test who can see the number

Use realistic roles, including a user who must be denied another business unit’s data. Test filters, downloads, cached results and scheduled emails as well as the dashboard page. A UI filter alone is not an authorization boundary. [PostgreSQL’s row-security documentation](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) shows that policies and roles affect enforcement, including special treatment of table owners. Test the identity actually used by the reporting tool, not an unrelated administrator.

Minimize personal fields to what the agreed report needs. Name the data owner and involve the appropriate privacy or legal specialist in retention and deletion decisions. Do not copy production customer records into an unrestricted demonstration account. Redacted or synthetic fixtures are enough to establish many acceptance behaviors.

### Hand over a decision record, not only a dashboard

The acceptance pack should include the metric contract, source inventory, lineage, versioned transformations, failing and passing fixtures, access evidence, freshness status, restore/replay procedure and a named operational owner. Record exceptions explicitly: an accepted gap needs impact, owner and review date. No written exception should silently turn an unavailable source into a complete metric.

Use the [software handover checklist](/software-development-guide/software-handover-checklist/) for account and repository ownership. The point of acceptance is that a business owner can explain the number and an operator can safely recover its path. A larger warehouse, additional streaming infrastructure or an AI interface is a separate decision when the actual reporting need justifies it.

// 03

## Where this usually goes wrong

- Accepting a plausible chart without reconciling its inputs
- Calling a successful load fresh when the source data is stale
- Running a replay that counts the same payment twice
- Testing permissions only with the administrator account

// 04

## The checklist

Agree the evidence before implementation begins.

1. Name one business decision, metric and accountable owner
2. Define grain, timezone, currency and correction policy
3. List authoritative sources, expected keys and source watermarks
4. Approve small fixtures with duplicates, late arrivals and invalid records
5. Set publication, quarantine and freshness behavior explicitly
6. Demonstrate replay and a partial-run recovery
7. Test allowed and denied roles, exports and cached output
8. Hand over code, definitions, monitoring and recovery responsibility

// 05

## What this looks like in our work

The Bond Analytics Platform case documents Excel ingestion, row-level validation and repeatable snapshot analysis. It supports those engineering capabilities; the synthetic order/refund fixture and proposed acceptance process here are not that client’s implementation.

### [Bond Analytics Platform](/case-studies/bond-analytics/)
- **Status:** Live
- **Outcome:** 2 months - 0 to Enterprise
- **Summary:** Institutional bond analytics platform, zero to enterprise-ready in 2 months; raised multiple rounds.
- **Stack:** NestJS, React, Typescript

These are selected projects, not our full portfolio. We have shipped 100+ products since 2018.

// 06

## Related services & reading

- [SERVICE Data Engineering](/services/data-engineering/)
- [GUIDE Software handover checklist](/software-development-guide/software-handover-checklist/)
- [GUIDE Software QA checklist](/software-development-guide/software-qa-checklist-before-launch/)
- [CASE STUDY Bond Analytics Platform](/case-studies/bond-analytics/)

// 07

## FAQs

### What is the difference between data quality and pipeline acceptance?

Data quality tests examine properties such as missing values, uniqueness and valid references. Pipeline acceptance additionally checks the business definition, completeness, freshness, permissions, replay, recovery and operational ownership. A clean table can still answer the wrong question.

### Do we need real-time data for a useful dashboard?

Only when the business decision needs it and the sources can support it. Agree a freshness target, source watermark and stale-result behavior first. More frequent jobs cannot make an upstream source publish earlier or fix an undefined metric.

### How do you test whether retries double-count data?

Use stable identifiers, process the same bounded fixture twice and compare both record-level contributions and totals. In this example, a repeated order must not change EUR 170 net collected. Include a late refund and a recovery after partial execution, because a simple successful rerun is not enough.

### Who accepts a reporting pipeline?

A business owner accepts metric meaning and useful freshness; engineering demonstrates transformations and failure behavior; the authorized access owner approves visibility; operations accepts recovery and support responsibility. These roles can be held by fewer people, but their decisions must remain explicit.

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://wavect.io/#organization",
      "@type": [
        "Organization",
        "ProfessionalService",
        "LocalBusiness"
      ],
      "employee": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "founder": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "legalRepresentative": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "name": "Wavect GmbH",
      "subjectOf": {
        "@id": "https://wavect.io/verified-claims.json#dataset",
        "@type": "Dataset",
        "creator": {
          "@id": "https://wavect.io/#organization",
          "@type": [
            "Organization",
            "ProfessionalService",
            "LocalBusiness"
          ]
        },
        "description": "A machine-readable registry of quantitative and qualitative claims published by Wavect, with review dates, localized page appearances and public third-party citations where available.",
        "inLanguage": "en",
        "isAccessibleForFree": true,
        "license": "https://creativecommons.org/licenses/by/4.0/",
        "name": "Wavect verified publication claims",
        "url": "https://wavect.io/verified-claims.json"
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/team/kevin-riedl/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Kevin Riedl",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796365",
        "https://www.linkedin.com/in/wsdt",
        "https://github.com/wsdt"
      ],
      "url": "https://wavect.io/team/kevin-riedl/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/team/christof-jori/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Christof Jori",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796367",
        "https://www.linkedin.com/in/jocr77/",
        "https://github.com/jo-chris"
      ],
      "url": "https://wavect.io/team/christof-jori/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/#website",
      "@type": "WebSite",
      "inLanguage": [
        "en",
        "de",
        "es",
        "zh"
      ],
      "name": "Wavect",
      "potentialAction": {
        "@type": "SearchAction",
        "query-input": "required name=search_term_string",
        "target": {
          "@type": "EntryPoint",
          "urlTemplate": "https://wavect.io/search/?q={search_term_string}"
        }
      },
      "publisher": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/software-development-guide/data-pipeline-acceptance-checklist/#webpage",
      "@type": "WebPage",
      "dateModified": "2026-11-04",
      "inLanguage": "en",
      "isPartOf": {
        "@id": "https://wavect.io/#website",
        "@type": "WebSite"
      },
      "lastReviewed": "2026-11-04",
      "url": "https://wavect.io/software-development-guide/data-pipeline-acceptance-checklist/"
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://wavect.io/software-development-guide/data-pipeline-acceptance-checklist/#article",
      "@type": "Article",
      "about": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "author": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "dateModified": "2026-11-04",
      "datePublished": "2026-11-03",
      "description": "Accept the path from source records to a business decision, not just a dashboard screenshot. Use a worked order-and-refund example, freshness and replay tests, access checks and a handover record to define reliable reporting.",
      "headline": "How do you know a data pipeline is ready for reporting?",
      "inLanguage": "en",
      "isPartOf": {
        "@id": "https://wavect.io/#website",
        "@type": "WebSite"
      },
      "mainEntityOfPage": "https://wavect.io/software-development-guide/data-pipeline-acceptance-checklist/#webpage",
      "mentions": [
        {
          "@id": "https://wavect.io/#organization",
          "@type": [
            "Organization",
            "ProfessionalService",
            "LocalBusiness"
          ]
        },
        {
          "@type": "Service",
          "name": "Data Engineering",
          "url": "https://wavect.io/services/data-engineering/"
        }
      ],
      "name": "How do you know a data pipeline is ready for reporting?",
      "publisher": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "speakable": {
        "@type": "SpeakableSpecification",
        "cssSelector": [
          ".cmp-hero__headline",
          ".cmp-hero__lead"
        ]
      },
      "url": "https://wavect.io/software-development-guide/data-pipeline-acceptance-checklist/"
    },
    {
      "@type": "BreadcrumbList",
      "itemListElement": [
        {
          "@type": "ListItem",
          "item": "https://wavect.io/",
          "name": "Home",
          "position": 1
        },
        {
          "@type": "ListItem",
          "item": "https://wavect.io/software-development-guide/",
          "name": "Software development guide",
          "position": 2
        },
        {
          "@type": "ListItem",
          "item": "https://wavect.io/software-development-guide/data-pipeline-acceptance-checklist/",
          "name": "How do you know a data pipeline is ready for reporting?",
          "position": 3
        }
      ]
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Data quality tests examine properties such as missing values, uniqueness and valid references. Pipeline acceptance additionally checks the business definition, completeness, freshness, permissions, replay, recovery and operational ownership. A clean table can still answer the wrong question."
      },
      "name": "What is the difference between data quality and pipeline acceptance?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Only when the business decision needs it and the sources can support it. Agree a freshness target, source watermark and stale-result behavior first. More frequent jobs cannot make an upstream source publish earlier or fix an undefined metric."
      },
      "name": "Do we need real-time data for a useful dashboard?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use stable identifiers, process the same bounded fixture twice and compare both record-level contributions and totals. In this example, a repeated order must not change EUR 170 net collected. Include a late refund and a recovery after partial execution, because a simple successful rerun is not enough."
      },
      "name": "How do you test whether retries double-count data?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "A business owner accepts metric meaning and useful freshness; engineering demonstrates transformations and failure behavior; the authorized access owner approves visibility; operations accepts recovery and support responsibility. These roles can be held by fewer people, but their decisions must remain explicit."
      },
      "name": "Who accepts a reporting pipeline?"
    }
  ],
  "speakable": {
    "@type": "SpeakableSpecification",
    "cssSelector": [
      ".faq-question",
      ".faq-answer"
    ]
  }
}
```
