> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dqlabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Scoring

> The Score entity stores data quality metrics and scoring results for assets — the foundation of Prizm's quality monitoring and reporting.

<script type="application/ld+json">
  {`{
            "@context": "https://schema.org",
            "@type": "TechArticle",
            "headline": "Scoring",
            "description": "The Score entity stores data quality metrics and scoring results for assets - the foundation of Prizm's quality monitoring and reporting.",
            "url": "https://docs.dqlabs.ai/architecture/score",
            "publisher": {
              "@type": "Organization",
              "name": "DQLabs Inc",
              "logo": "https://media.brand.dev/332adc35-5bc4-4d2b-bf78-256aa4a5e414.svg"
            }
            }`}
</script>

## Overview

The **Score** entity captures the result of every data quality check performed by Prizm. It records both raw validation statistics (valid/invalid counts) and derived quality scores, along with full context about the asset, metric, and execution run that produced the result.

Score is central to Prizm's historical quality tracking, trend analysis, and root cause analysis.

## Data Flow

When a data quality check is performed, the following steps occur:

<Steps>
  <Step title="Metric Applied">
    A quality metric is applied to a data asset (referenced by `asset_id`).
  </Step>

  <Step title="Validation Executed">
    The metric engine scans the asset and counts valid and invalid records.
  </Step>

  <Step title="Score Computed">
    `valid_percentage`, `invalid_percentage`, and overall `score` are calculated.
  </Step>

  <Step title="Score Record Created">
    A new Score record is written with full context — asset, metric, run, timestamps, and personnel.
  </Step>

  <Step title="Exception Generation">
    If `invalid_records > 0`, Exception records are created and routed to the appropriate workflow.
  </Step>
</Steps>

***

## Score vs. Exception

<Note>
  The **Score** entity represents the aggregate result of a quality check (e.g., "5% of records had null order IDs"). **Exceptions** are the individual failing records themselves. Scores drive dashboards and trends; Exceptions drive remediation workflows.
</Note>

***

## How we score?

Every quality score in the platform is built the same way, bottom-up: individual **measures** (data quality checks) produce a 0–100 score, and those scores are combined using **weightage** at each level until they roll up into a single score for an attribute, an asset, a pipeline, or a logical grouping like a domain, product, tag, or application.

```text theme={null}
Measure Score (per check)
   └─► Attribute Score (weighted avg of measures on that attribute)
          └─► Asset Score (weighted avg of attribute + asset-level measures)
                 └─► Logical Group Score (avg of asset scores in that Domain / Product / Tag / Application)

Pipeline Score is calculated separately using its own category-based model (see below).
```

<Info>
  Not every asset type gets a **calculated** score — some (like dashboards, reports, and workbooks) **propagate** a score from their upstream lineage instead. See [Which asset types get a score](#which-asset-types-get-a-score) below.
</Info>

## Which metrics feed the quality score

Not every metric the platform collects contributes to the Quality Score. The Metrics Tracker draws a clear line between metrics that are **scored** (feed into the Attribute/Asset Quality Score) and metrics that are **monitored** (drive alerting and observability, but are tracked separately from the score).

### Explicitly excluded from scoring: Availability / monitoring metrics

The following metrics are marked `Score = No` in the tracker, even though they're actively monitored (`Monitor = Yes`) and can raise alerts:

| Metric                | Subcategory | Dimension    | Level |
| --------------------- | ----------- | ------------ | ----- |
| Freshness             | Freshness   | Availability | Asset |
| Last Updated          | Freshness   | Timeliness   | Asset |
| Row (row count)       | Volume      | Completeness | Asset |
| Data Size             | Volume      | Completeness | Asset |
| Volume                | Volume      | Completeness | Asset |
| Duplicates            | Duplicate   | Uniqueness   | Asset |
| Column (column count) | Schema      | Validity     | Asset |
| Schema                | Schema      | Validity     | Asset |
| Schema Name           | Schema      | Validity     | Asset |

<Info>
  These are exactly the metrics consolidated under **Observe and Reliability** monitoring (Volume, Freshness, Schema, Duplicates) — they answer "is this asset behaving as expected?" rather than "how good is this data?", so they surface as alerts and issues instead of moving the Quality Score.
</Info>

### Metrics that do feed the quality score: profiling measures

The measures that carry a configurable **weightage** and roll into the Attribute Score (per the formula above) are the attribute-level profiling checks under the **Distribution** and **Frequency** categories — these map to the Completeness, Validity, and Uniqueness dimensions:

| Category         | Example Metrics                                                                                                                                                                                                     | Dimension(s)                       |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| **Distribution** | Null Count, Empty / Non-Empty, Space, Distinct, Repeating, Character / Digit / Alphabet / Alpha Numeric / Special Character, Leading / Trailing / Inner / Outer Space, Whitespace, Negative / Positive / Zero Value | Completeness, Validity, Uniqueness |
| **Frequency**    | Max/Min Length, Length Range, Max/Min Value, Value Range, Enum, Regular Expressions, Long/Short Pattern                                                                                                             | Validity                           |

Each is tagged with a **Profile Type** of `Essential` or `Advanced`, which controls whether it runs by default or needs to be explicitly enabled — but either way, once configured with a weightage, it contributes to the attribute's score.

### Informational, not scored: Statistics, Performance, and Cost metrics

Three further categories exist in the tracker but sit outside the Quality Score entirely:

| Category        | Example Metrics                                                                         | Level                | Purpose                                                                                                                      |
| --------------- | --------------------------------------------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Statistics**  | Mean, Median, Mode, Standard Deviation, Variance, Skewness, Kurtosis, Q1/Q3, Sum, Range | Attribute            | Descriptive/statistical profiling — useful for anomaly detection and understanding data shape, not a pass/fail quality check |
| **Performance** | Avg Blocked, Avg Queue Load, Avg Running, Database Storage                              | Warehouse / Database | Platform/infrastructure performance monitoring                                                                               |
| **Cost**        | Credits Used                                                                            | Warehouse / Database | Compute cost tracking                                                                                                        |

<Note>
  If you're configuring measures and don't see a Quality Score move after enabling a Statistics, Performance, or Cost metric, this is expected — these are informational and operational signals, not scoring inputs. To influence the Quality Score, configure weightage on a Distribution or Frequency category measure instead.
</Note>

## Measure and attribute-level scoring

### Weighted measure score

Every measure attached to an attribute has a **weightage** (its relative importance) and produces a **score** (0–100) when it runs. The weighted contribution of a single measure is:

$$
\text{Weighted Score} = \frac{\text{Weightage} \times \text{Score}}{100}
$$

### Overall attribute score

The attribute's overall score is the weighted average across all measures configured on it:

$$
\text{Attribute Score} = \frac{\sum(\text{Weighted Scores})}{\sum(\text{Weightages})}
$$

This means a measure with higher weightage moves the attribute's score more than a low-weightage measure, even if both report the same raw score.

<Accordion title="Special case: JSON / nested attributes">
  For JSON (variant) attributes, scoring happens in two layers before it becomes a single attribute score:

  1. **Key-level measures** — each key/sub-attribute inside the JSON structure is scored individually using standard measures (null check, min/max length, etc.), then combined into a single **Overall Key Score** using the same weighted-average formula as above.
  2. **Attribute-level measures** — checks applied to the JSON column as a whole (e.g. schema validity).

  If both layers exist, the final attribute score blends them:

  $$
  \text{Attribute Score} = \frac{\text{Overall Key Score} + \text{Attribute-Level Measure Score}}{2}
  $$

  This keeps detailed key-level checks and high-level structural checks balanced in a single score.
</Accordion>

## Asset-level score aggregation

The asset score uses the **same weighted-average pattern** as the attribute score, just one level up: every attribute score (and any asset-level measures) becomes an input, each with its own weightage, and the asset score is the weighted average of all of them.

$$
\text{Asset Score} = \frac{\sum(\text{Weighted Scores})}{\sum(\text{Weightages})}
$$

In practice this means a composite attribute score (including a JSON attribute's blended score) is treated as **one measure** feeding into the asset score, typically at a configured weightage (100 by default), alongside every other attribute on the asset.

## Grouped scoring (DQ Score Aggregation by Grouping Parameter)

For measures that evaluate data **grouped by a key** — for example, scoring completeness per `Customer_ID` or `VIN` rather than for the table as a whole — the platform supports a dedicated grouping mode with its own four-level rollup:

| Level                                    | Calculation                                                                 |
| ---------------------------------------- | --------------------------------------------------------------------------- |
| **Measure Score per Attribute** (Detail) | Each measure is evaluated per attribute, per group-by value                 |
| **Attribute Score per Group** (Summary)  | Average of all selected measure scores for that attribute, within the group |
| **Group Total Score**                    | Average of all attribute scores within that group                           |
| **Aggregated DQ Score**                  | Average of all group total scores                                           |

This lets you define the scope once (e.g. "group by Customer ID"), apply multiple measures across multiple attributes in a single pass, and see both the group-level breakdown and the overall aggregated score — instead of re-running a separate scope query per attribute.

<Note>
  Grouped scoring is only available for standalone measures, and only for a defined set of out-of-the-box measures (e.g. `null_count`, `distinct_count`, `duplicate`, `min_length`, `max_length`, `min_value`, `max_value`, `mean`, `median`, `standard_deviation`, and similar statistical/profiling checks).
</Note>

## Pipeline scoring

Pipeline scoring is fundamentally different from table/attribute scoring: there's **no single universal denominator**. Instead, each pipeline metric type (called a "signal") defines its own scoring strategy, and signals roll up into three health categories before producing a final score.

### Signal scoring strategies

<AccordionGroup>
  <Accordion title="A. Binary metrics — Execution Status, Platform Outage">
    Pass = **100**, fail = **0**. No warmup required; can alert from run 1.

    ```python theme={null}
    score = 100 if is_success else 0
    ```
  </Accordion>

  <Accordion title="B. Window percentage metric — Failure Rate">
    Computed over the last N runs (default 10–30). No warmup required.

    ```python theme={null}
    success_rate = (successful_runs / total_runs) * 100
    score = success_rate
    ```

    If the stored value is already a failure-rate percentage: `score = max(0, 100 - failure_rate_value)`.
  </Accordion>

  <Accordion title="C. Deadline-relative metric — Freshness">
    Score decays from 100 as actual completion drifts later than the expected schedule. Alerting is typically suppressed until a baseline exists.

    ```python theme={null}
    delay_ratio = max(0, (actual_ts - expected_ts).seconds / sla_buffer_seconds)
    score = max(0, 100 - (delay_ratio * 100))
    ```
  </Accordion>

  <Accordion title="D. Percentile-baseline metrics — Execution Time, Rows Affected">
    Uses a rolling baseline (e.g. p50 over the last 10+ runs). Score reflects how far the current value deviates from that baseline. Requires warmup — alerts are suppressed until enough history exists and the baseline is stable.
  </Accordion>
</AccordionGroup>

### Warmup and alert suppression

Warmup is evaluated **per metric**, not per pipeline:

* Binary metrics (Execution Status, Platform Outage) score and can alert from run 1.
* Baseline-dependent metrics (Execution Time, Rows Affected, and often Freshness) wait until at least **10 runs** of history exist before they produce a score or alert.

<Note>
  This **10-run** warmup is specific to baseline-dependent **pipeline** signals and is a separate mechanism from the **Learning mode** warmup used for standard asset-level metric anomaly detection (Structural, Operational, Business, etc.), which requires more than 5 historical collection runs — see [What Prizm Collects from Snowflake](/sources/snowflake/what-we-collect). Both thresholds are counted in collection/execution runs, not elapsed time.
</Note>

* For volatile metrics like Rows Affected, the platform also checks the **coefficient of variation** (`CV = stddev / mean`) over the lookback window. If `CV` exceeds a threshold (default **0.5**), the metric is marked **baseline unstable** and alerts are suppressed until the pattern settles.

### Weight profiles (alert modes)

Pipeline signals roll up into three categories — **Reliability**, **Timeliness**, and **Volume** — weighted according to the selected alert mode:

| Mode                     | Reliability | Timeliness | Volume |
| ------------------------ | ----------- | ---------- | ------ |
| **Default**              | 50%         | 30%        | 20%    |
| **Mad Max** (tolerant)   | 30%         | 20%        | 50%    |
| **Hurry** (SLA-critical) | 40%         | 50%        | 10%    |

### Category composition

| Category        | Inputs                                          | Aggregation                           |
| --------------- | ----------------------------------------------- | ------------------------------------- |
| **Reliability** | Execution Status, Platform Outage, Failure Rate | Average of active signal scores       |
| **Timeliness**  | Freshness, Execution Time                       | Average of active signal scores       |
| **Volume**      | Rows Affected                                   | The signal score itself (when active) |

### Final score calculation

If a category has **no active signals** (e.g. still in warmup), it's excluded and its weight is redistributed across the remaining active categories:

$$
\text{Final Score} = \frac{\sum(\text{Active Category Score} \times \text{Category Weight})}{\sum(\text{Active Category Weights})}
$$

**Capping rule:** if the most recent run **failed** (Execution Status score = 0), the final score is capped at a configured ceiling (e.g. **40**) regardless of how other categories score. This ensures a failed run always meaningfully impacts the overall pipeline score.

<Accordion title="Worked example — two consecutive runs">
  **Run 1** — only Reliability is active (Timeliness and Volume are still in warmup):

  | Metric           | Value  | Score |
  | ---------------- | ------ | ----- |
  | Execution Status | Failed | 0     |
  | Platform Outage  | None   | 100   |
  | Failure Rate     | 100%   | 0     |

  `Reliability = (0 + 100 + 0) / 3 = 33.3` → only Reliability is active, so **Final Score = 33.3**.

  **Run 2** — Timeliness signals now have a baseline:

  | Metric           | Value     | Baseline    | Score                     |
  | ---------------- | --------- | ----------- | ------------------------- |
  | Execution Status | Failed    | —           | 0                         |
  | Platform Outage  | None      | —           | 100                       |
  | Failure Rate     | 100%      | 100         | 0                         |
  | Execution Time   | 23,000ms  | 342,000ms   | 100 (well below baseline) |
  | Freshness        | 390,660ms | 6,737,256ms | 100 (well below baseline) |

  `Reliability = 33.3`, `Timeliness = 100`, `Volume = NULL` (still warming up, excluded):

  $$
  \text{Final Score} = \frac{(33.3 \times 0.5) + (100 \times 0.3)}{0.5 + 0.3} = \frac{66.25}{0.8} = 82.8
  $$

  Note the score rose sharply between two consecutive **failed** runs, because Timeliness recovered. This is exactly the scenario the failed-run capping rule exists to guard against — without a cap, a pipeline that fails but finishes fast can still show a deceptively high score.
</Accordion>

## Logical group scoring (Domain, Product, Tag, Application)

Domains, Products, Tags, and Applications are **logical groupings** of assets rather than assets themselves — they don't have their own measures. Their quality score is a **rollup of the calculated or propagated scores of the assets that belong to them**:

$$
\text{Group Score} = \text{Average of Quality Scores of all member assets}
$$

This applies uniformly across the four grouping dimensions:

| Grouping        | What it aggregates                                              |
| --------------- | --------------------------------------------------------------- |
| **Domain**      | All assets tagged to that business domain (and its sub-domains) |
| **Product**     | All assets that make up that data product                       |
| **Tag**         | All attributes/assets carrying that tag                         |
| **Application** | All assets belonging to that publishing or consuming system     |

These rollups power dashboard widgets such as **Score by Domain/Tag/Application/Term**, **Overall Quality**, and **Organization Score**, which show the aggregated score for each grouping alongside the count of contributing assets, alerts, and issues.

<Note>
  Because group scores are simple averages of member asset scores, a single low-scoring but highly critical asset can be diluted by many high-scoring, low-criticality assets in the same group. Use the asset-level Criticality score alongside the group Quality score to prioritize which member assets need attention first.
</Note>

## Which asset types get a score

Not every object in the catalog is scored the same way. Some asset types get a **calculated** score from their own measures; others **propagate** a score from upstream lineage; a few don't carry a score at all.

| Asset Type                                                     | Scored?        | Calculated or Propagated                                                        |
| -------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------------- |
| Table / View / External Table / other table types              | Yes            | Calculated                                                                      |
| Worksheet (Extract, no data source link)                       | No             | —                                                                               |
| Worksheet (linked to a data source / blended / semantic layer) | Yes            | Propagated (based on the attributes it uses)                                    |
| Workbook, Report, Dashboard                                    | No score shown | Propagated for alerts/issues only, dependent on lineage                         |
| Pipeline                                                       | Yes            | Calculated (see [Pipeline scoring](#pipeline-scoring))                          |
| Job (e.g. dbt Job)                                             | Yes            | Calculated                                                                      |
| Task (Airflow, ADF, Snowflake/Databricks tasks)                | Yes            | Calculated                                                                      |
| Stored Procedure / Function                                    | No             | —                                                                               |
| dbt Model                                                      | Yes            | Propagated from the underlying materialized asset, or calculated from dbt tests |
| dbt Test                                                       | Yes            | Calculated                                                                      |
| DAG (Airflow and similar)                                      | Yes            | Calculated from DAG-level metrics                                               |
| Notebook                                                       | Yes            | Calculated from associated metrics                                              |

<Tip>
  For asset types that propagate rather than calculate, the score displayed is inherited through lineage — if the upstream table's score changes, the downstream worksheet, report, or dbt model's displayed score changes with it.
</Tip>

## Related pages

<CardGroup cols={2}>
  <Card title="Usage" icon="chart-line" href="/architecture/usage">
    See how usage feeds into an asset's criticality score
  </Card>

  <Card title="Audit & Activity Overview" icon="layer-group" href="/architecture/log/logging-overview">
    See where score-affecting changes are logged
  </Card>
</CardGroup>

***
