> ## 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.

# Overview

> How Metric Templates (Rule Library) let you write a parameterized SQL rule once and assign it to many assets, each with its own parameter overrides.

<script type="application/ld+json">
  {`{
            "@context": "https://schema.org",
            "@type": "TechArticle",
            "headline": "Metric Templates Overview",
            "description": "How Metric Templates (Rule Library) let you write a parameterized SQL rule once and assign it to many assets, each with its own parameter overrides.",
            "url": "https://docs.dqlabs.ai/architecture/metrics/metric-template/overview",
            "publisher": {
              "@type": "Organization",
              "name": "DQLabs Inc",
              "logo": "https://media.brand.dev/332adc35-5bc4-4d2b-bf78-256aa4a5e414.svg"
            }
            }`}
</script>

A **Metric Template** is a reusable parameterized SQL rule stored in the **Rule Library**. Write the quality logic once, assign it to any number of assets, and let each assignment carry its own parameter overrides. When the template changes, all assignments update on their next run — no manual edits across dozens of metrics.

**Navigate to:** Click the **Metric Template** button at the top of the Metrics page to switch from the metric list to the Rule Library.

<Note>
  Metric Templates have a **separate permission set** from standard Metrics. Access must be granted explicitly in your organization's RBAC configuration — having Metric access does not automatically grant Template access.
</Note>

***

## Template vs. standalone parameterized metric

|                           | Standalone parameterized metric | Metric Template                         |
| ------------------------- | ------------------------------- | --------------------------------------- |
| **Scope**                 | Single asset                    | Reusable across many assets             |
| **Managed in**            | Metric list                     | Rule Library                            |
| **Applied via**           | Direct configuration            | Assignment per asset                    |
| **Per-asset overrides**   | Set at metric level             | Set per assignment                      |
| **Propagation on update** | No                              | Yes — 12 fields sync to all assignments |
| **Access control**        | Metric permission               | Separate Template permission            |

***

## Template Dashboard

The Metric Template page opens with three summary cards:

| Card                          | What it shows                                    |
| ----------------------------- | ------------------------------------------------ |
| **Total Metric Templates**    | All templates in the library, active or inactive |
| **Active Metric Templates**   | Templates currently enabled and assignable       |
| **Inactive Metric Templates** | Templates that have been deactivated             |

***

## Attribute-only templates

If the SQL contains `{{column}}` or `{{attribute}}`, Prizm flags the template as **Attribute-only** — it can only be assigned to column-level objects, not table-level assets. If neither token appears, the template can be assigned to either Assets or Attributes.

***

## Use cases

### Regional REGEX validation (MTART)

**Business need:** Validate that the `MTART` (Material Type) column matches the allowed format for each region. The format differs by region and the rule applies to dozens of tables.

Without templates: one metric per region per table — dozens of near-identical metrics to maintain.<br />With a template: one definition, one assignment per region/table, each with its own REGEX override.

**Template SQL:**

```sql theme={null}
SELECT COUNT(*) AS failing_rows
FROM {{table}}
WHERE MTART IS NOT NULL
  AND NOT REGEXP_LIKE(MTART, {{mtart_regex}})
```

**Assignments:**

| Asset            | `mtart_regex` override |
| ---------------- | ---------------------- |
| `PROD.EMEA.MARA` | `^(FERT\|HALB\|ROH)$`  |
| `PROD.APAC.MARA` | `^(FERT\|VERP)$`       |
| `PROD.NA.MARA`   | `^[A-Z]{4}$`           |

Updating the template SQL (e.g., adding a WHERE clause to exclude archived records) automatically propagates to all three assignments.

***

### Territory ENUM allowlist check

**Business need:** Ensure every `Territory` value in the sales table is one of the approved codes. The approved list differs per region.

```sql theme={null}
SELECT COUNT(*) AS invalid_territory_count
FROM {{table}}
WHERE territory NOT IN ({{allowed_territories}})
  AND record_date >= {{start_date}}
```

| Parameter                 | Category | Notes                                            |
| ------------------------- | -------- | ------------------------------------------------ |
| `{{table}}`               | SOURCE   | Auto-resolved                                    |
| `{{allowed_territories}}` | CONSTANT | Org-level ENUM: `South`, `North`, `West`, `East` |
| `{{start_date}}`          | METADATA | Defaults to 30 days ago                          |

Each sales region table gets its own assignment with its own `allowed_territories` override.

***

### Cross-asset null check

**Business need:** Apply the same null-rate check on a specific column across many tables. The column name varies per table.

```sql theme={null}
SELECT
  ROUND(
    COUNT(CASE WHEN {{attribute}} IS NULL THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0),
    2
  ) AS null_rate_pct
FROM {{table}}
```

Both `{{table}}` and `{{attribute}}` are SOURCE parameters — they resolve automatically from the column selected in the asset configuration. No manual override required.

***

### Freshness SLA with configurable window

**Business need:** Different tables have different acceptable freshness windows — hourly, daily, or weekly. One template handles all with a `max_hours` override per assignment.

```sql theme={null}
SELECT DATEDIFF(HOUR, MAX(updated_at), CURRENT_TIMESTAMP()) AS hours_since_update
FROM {{table}}
```

**Pass criteria:** Metric value must be `<= {{max_hours}}` (set via Custom Threshold using the parameter).

| Asset       | `max_hours` override |
| ----------- | -------------------- |
| `ORDERS`    | `2`                  |
| `CUSTOMERS` | `25`                 |
| `PRODUCTS`  | `72`                 |

Three SLA policies. One template. Zero metric duplication.

***

### Real-world SQL complexity examples

#### Completeness check — reserved keywords only

**Template:** `C_POLICY_EFF_DATE_COMPLETENESS`

```sql theme={null}
SELECT * FROM {{table}} WHERE {{column}} IS NULL
```

Both tokens are SOURCE — resolved from the assigned attribute. No popup input needed.

**Resolved SQL for attribute `POL_EFF_DT`:**

```sql theme={null}
SELECT * FROM dqlabs_cx.underwriting.underwriting WHERE POL_EFF_DT IS NULL
```

***

#### Date validity — reserved + one custom parameter

**Template:** `POL_EFF_DATE_VALIDITY`

```sql theme={null}
SELECT * FROM {{table}} WHERE {{column}} = {{stale_date}}
```

| Parameter        | Category | Required                       |
| ---------------- | -------- | ------------------------------ |
| `{{table}}`      | SOURCE   | Auto-resolved                  |
| `{{column}}`     | SOURCE   | Auto-resolved (Attribute-only) |
| `{{stale_date}}` | CONSTANT | Yes — user must supply         |

Assignment opens a parameter input pane requesting `stale_date`. User enters `1900-01-01`.

**Resolved SQL:**

```sql theme={null}
SELECT * FROM dqlabs_cx.underwriting.underwriting WHERE POL_EFF_DT = '1900-01-01'
```

***

#### Cross-table join check — reserved + custom identifier and value

**Template:** `PREMIUM_TRANS_CODE_MISMATCH`

```sql theme={null}
SELECT * FROM {{table}} prl
JOIN {{join_table_1}} pt ON prl.PRL_KEY = pt.PRL_KEY
AND DAC_CD <> {{code}}
```

| Parameter          | Category | Notes                                          |
| ------------------ | -------- | ---------------------------------------------- |
| `{{table}}`        | SOURCE   | Auto-resolved                                  |
| `{{join_table_1}}` | CONSTANT | User supplies the join target table            |
| `{{code}}`         | CONSTANT | User supplies the distribution code to exclude |

No `{{column}}` → can be assigned at **Asset or Attribute level**.

**Resolved SQL:**

```sql theme={null}
SELECT * FROM dqlabs_cx.underwriting.underwriting prl
JOIN "AIGI_EDR_ABSTRACTION"."AbstractLayer"."PREM_TRANS" pt
  ON prl.PRL_KEY = pt.PRL_KEY
AND DAC_CD <> 'C'
```

<Card title="Setup" icon="sliders" href="/architecture/metrics/metric-template/setup">
  Step-by-step: create a template, assign to assets, propagation fields, and Run All.
</Card>
