Plantilla de Reglas de Calidad de Datos (SQL + dbt)
Una plantilla lista para copiar y definir reglas de validación por dataset y columna, con niveles de severidad, checks SQL, tests de dbt y una suite de Great Expectations.
Visión General
Un dashboard muestra que los ingresos cayeron 40% de la noche a la mañana. El negocio entra en pánico hasta que alguien revisa el origen: una columna currency con nulos que rompió la conversión de moneda. Nada en el pipeline falló porque nada estaba verificando. Las reglas de calidad de datos son la definición explícita de qué significa “dato bueno” para cada dataset y columna, verificada automáticamente en cada ejecución.
Esta plantilla cubre las seis dimensiones de calidad (completitud, consistencia, exactitud, actualidad, unicidad y validez) como una tabla de reglas que puedes adaptar a tus propios datasets, además de configuraciones funcionales para tests de dbt y Great Expectations. Para una visión más amplia de profiling y monitoreo de datos, consulta la Guía de Data Quality. Si tus reglas viven dentro de modelos dbt, la receta sobre transformar datos en el warehouse con dbt cubre la parte del modelo.
Cuándo Usar
- Definir checks de calidad para un pipeline nuevo antes de que llegue a producción.
- Establecer data contracts entre productores y consumidores, donde cada lado necesita una definición escrita y testeable de qué datos son aceptables.
- Configurar tests de dbt o suites de Great Expectations sobre tablas existentes.
- Cumplir requisitos de compliance que exigen validación documentada (SOC 2, obligaciones de exactitud de GDPR, conciliación financiera).
- Incorporar datasets nuevos a una plataforma de datos para dejar escritas la propiedad y las expectativas.
- Diagnosticar un incidente de datos y formalizar los checks que lo habrían detectado antes.
No uses esta plantilla para validaciones puntuales en notebooks exploratorios o scripts ad-hoc; ahí alcanza con un par de aserciones inline. Tampoco tiene sentido en datasets sin consumidores downstream, donde un check fallido no bloquea nada.
Solución
La plantilla documenta las reglas de una tabla de hechos fct_orders. Cópiala y reemplaza el dataset, las columnas y los umbrales con los tuyos.
# Data Quality Rules — `<Dataset Name>`
## Rules Overview
| Field | Value |
|-------|-------|
| Dataset | fct_orders |
| Schema | marts |
| Database | analytics |
| Owner | Data Platform Team |
| Last Updated | 2026-07-05 |
| Total Rules | 28 |
| Critical Rules | 12 |
| Warning Rules | 16 |
| Framework | dbt tests + Great Expectations |
| Execution | Post-load, pre-consumer access |
## 1. Quality Dimensions
| Dimension | Description | Example |
|-----------|-------------|---------|
| Completeness | Required fields are not null | order_id must never be null |
| Consistency | Data conforms to expected format and relationships | currency must be valid ISO 4217 code |
| Accuracy | Values fall within expected ranges | total_amount must be positive |
| Timeliness | Data is fresh enough for its purpose | Data must be < 24 hours old |
| Uniqueness | No duplicate records | order_id must be unique |
| Validity | Values match expected patterns | email must match regex pattern |
## 2. Column-Level Rules
### order_id
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-001 | Not null | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders WHERE order_id IS NULL` | Fail pipeline |
| DQ-002 | Unique | Uniqueness | Critical | `SELECT order_id, COUNT(*) FROM fct_orders GROUP BY order_id HAVING COUNT(*) > 1` | Fail pipeline |
| DQ-003 | Format: starts with "ord_" | Validity | Critical | `SELECT COUNT(*) FROM fct_orders WHERE order_id NOT LIKE 'ord_%'` | Fail pipeline |
| DQ-004 | Length between 8 and 64 chars | Validity | Warning | `SELECT COUNT(*) FROM fct_orders WHERE LENGTH(order_id) < 8 OR LENGTH(order_id) > 64` | Log + proceed |
### customer_id
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-005 | Not null | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders WHERE customer_id IS NULL` | Fail pipeline |
| DQ-006 | Exists in dim_customers | Consistency | Critical | `SELECT COUNT(*) FROM fct_orders o LEFT JOIN dim_customers c ON o.customer_id = c.customer_id WHERE c.customer_id IS NULL` | Fail pipeline |
| DQ-007 | Format: starts with "cus_" | Validity | Warning | `SELECT COUNT(*) FROM fct_orders WHERE customer_id NOT LIKE 'cus_%'` | Log + proceed |
### order_date
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-008 | Not null | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders WHERE order_date IS NULL` | Fail pipeline |
| DQ-009 | Not in future | Accuracy | Critical | `SELECT COUNT(*) FROM fct_orders WHERE order_date > CURRENT_TIMESTAMP` | Fail pipeline |
| DQ-010 | Not older than 5 years | Accuracy | Warning | `SELECT COUNT(*) FROM fct_orders WHERE order_date < DATEADD(year, -5, CURRENT_DATE)` | Log + proceed |
| DQ-011 | Date matches partition | Consistency | Warning | `SELECT COUNT(*) FROM fct_orders WHERE DATE(order_date) != partition_date` | Log + proceed |
### status
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-012 | Not null | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders WHERE status IS NULL` | Fail pipeline |
| DQ-013 | Valid enum value | Validity | Critical | `SELECT COUNT(*) FROM fct_orders WHERE status NOT IN ('pending', 'processing', 'completed', 'cancelled', 'refunded')` | Fail pipeline |
### total_amount
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-014 | Not null | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders WHERE total_amount IS NULL` | Fail pipeline |
| DQ-015 | Greater than 0 | Accuracy | Critical | `SELECT COUNT(*) FROM fct_orders WHERE total_amount <= 0` | Fail pipeline |
| DQ-016 | Less than 100000 | Accuracy | Warning | `SELECT COUNT(*) FROM fct_orders WHERE total_amount >= 100000` | Log + proceed |
| DQ-017 | Matches sum of line items | Consistency | Critical | `SELECT COUNT(*) FROM fct_orders o JOIN fct_order_items i ON o.order_id = i.order_id GROUP BY o.order_id HAVING o.total_amount != SUM(i.line_total)` | Fail pipeline |
### currency
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-018 | Not null | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders WHERE currency IS NULL` | Fail pipeline |
| DQ-019 | Valid ISO 4217 code | Validity | Critical | `SELECT COUNT(*) FROM fct_orders WHERE currency NOT IN ('USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY', 'BRL', 'MXN')` | Fail pipeline |
| DQ-020 | Length is 3 | Validity | Warning | `SELECT COUNT(*) FROM fct_orders WHERE LENGTH(currency) != 3` | Log + proceed |
### payment_method
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-021 | Not null when status = completed | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders WHERE status = 'completed' AND payment_method IS NULL` | Fail pipeline |
| DQ-022 | Valid enum value | Validity | Warning | `SELECT COUNT(*) FROM fct_orders WHERE payment_method NOT IN ('credit_card', 'debit_card', 'paypal', 'bank_transfer', 'crypto', 'apple_pay', 'google_pay')` | Log + proceed |
## 3. Dataset-Level Rules
| Rule ID | Rule | Type | Severity | SQL | Action on Failure |
|---------|------|------|----------|-----|-------------------|
| DQ-023 | Row count > 0 | Completeness | Critical | `SELECT COUNT(*) FROM fct_orders` (must be > 0) | Fail pipeline |
| DQ-024 | Row count within expected range | Accuracy | Warning | `SELECT COUNT(*) FROM fct_orders` (must be between 100k and 10M) | Log + proceed |
| DQ-025 | Data is fresh (< 24h) | Timeliness | Critical | `SELECT MAX(_ingested_at) FROM fct_orders` (must be < 24h ago) | Fail pipeline |
| DQ-026 | No orphaned records | Consistency | Critical | `SELECT COUNT(*) FROM fct_orders o LEFT JOIN dim_customers c ON o.customer_id = c.customer_id WHERE c.customer_id IS NULL` | Fail pipeline |
| DQ-027 | All completed orders have payment events | Consistency | Warning | `SELECT COUNT(*) FROM fct_orders o WHERE o.status = 'completed' AND NOT EXISTS (SELECT 1 FROM fct_payment_events p WHERE p.order_id = o.order_id)` | Log + proceed |
| DQ-028 | Refund amounts don't exceed original | Accuracy | Critical | `SELECT COUNT(*) FROM fct_orders WHERE status = 'refunded' AND refund_amount > total_amount` | Fail pipeline |
## 4. dbt Test Configuration
### YAML Schema File
```yaml
version: 2
models:
- name: fct_orders
description: "Fact table containing all customer orders"
columns:
- name: order_id
description: "Unique order identifier"
tests:
- not_null
- unique
- accepted_values:
values: ["ord_%"]
quote: false
- name: customer_id
description: "Customer reference"
tests:
- not_null
- relationships:
to: ref('dim_customers')
field: customer_id
- name: order_date
description: "Order placement timestamp"
tests:
- not_null
- dbt_utils.expression_is_true:
expression: "order_date <= CURRENT_TIMESTAMP"
- name: status
description: "Order status"
tests:
- not_null
- accepted_values:
values: ['pending', 'processing', 'completed', 'cancelled', 'refunded']
- name: total_amount
description: "Order total in original currency"
tests:
- not_null
- dbt_utils.expression_is_true:
expression: "total_amount > 0"
- dbt_utils.expression_is_true:
expression: "total_amount < 100000"
- name: currency
description: "ISO 4217 currency code"
tests:
- not_null
- accepted_values:
values: ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY', 'BRL', 'MXN']
tests:
- dbt_utils.expression_is_true:
expression: "status != 'completed' OR payment_method IS NOT NULL"
name: completed_orders_have_payment_method
- dbt_utils.expression_is_true:
expression: "status != 'refunded' OR refund_amount <= total_amount"
name: refund_does_not_exceed_original
```
### Custom Test: Row Count Range
```sql
-- tests/assert_row_count_range.sql
{{ config(severity='WARN') }}
SELECT
CASE
WHEN COUNT(*) < 100000 THEN 'FAIL: row count below minimum'
WHEN COUNT(*) > 10000000 THEN 'FAIL: row count above maximum'
ELSE 'OK'
END AS result
FROM {{ ref('fct_orders') }}
HAVING result != 'OK'
```
### Custom Test: Data Freshness
```sql
-- tests/assert_data_freshness.sql
SELECT
EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - MAX(_ingested_at))) / 3600 AS hours_since_last_ingest
FROM {{ ref('fct_orders') }}
HAVING hours_since_last_ingest > 24
```
## 5. Great Expectations Suite
```python
import great_expectations as gx
suite = gx.ExpectationSuite("fct_orders_suite")
## Completeness
suite.add_expectation(gx.expect_column_values_to_not_be_null(column="order_id"))
suite.add_expectation(gx.expect_column_values_to_not_be_null(column="customer_id"))
suite.add_expectation(gx.expect_column_values_to_not_be_null(column="order_date"))
suite.add_expectation(gx.expect_column_values_to_not_be_null(column="total_amount"))
## Uniqueness
suite.add_expectation(gx.expect_column_values_to_be_unique(column="order_id"))
## Validity
suite.add_expectation(gx.expect_column_values_to_match_regex(
column="order_id",
regex=r"^ord_[a-zA-Z0-9]{5,60}$"
))
suite.add_expectation(gx.expect_column_values_to_be_in_set(
column="status",
value_set=["pending", "processing", "completed", "cancelled", "refunded"]
))
suite.add_expectation(gx.expect_column_values_to_be_in_set(
column="currency",
value_set=["USD", "EUR", "GBP", "JPY", "CAD", "AUD", "CHF", "CNY", "BRL", "MXN"]
))
## Accuracy
suite.add_expectation(gx.expect_column_values_to_be_between(
column="total_amount",
min_value=0.01,
max_value=100000
))
suite.add_expectation(gx.expect_column_values_to_be_between(
column="order_date",
min_value="2021-01-01",
max_value="2026-12-31"
))
## Consistency
suite.add_expectation(gx.expect_column_pair_values_A_to_be_greater_than_B(
column_A="total_amount",
column_B="refund_amount",
or_equal=True,
row_condition="status == 'refunded'",
condition_parser="pandas"
))
## Dataset-level
suite.add_expectation(gx.expect_table_row_count_to_be_between(min_value=100000, max_value=10000000))
```
## 6. Rule Execution and Reporting
### Execution Schedule
| When | Rules | Framework | Action |
|------|-------|-----------|--------|
| Post-staging load | DQ-001 to DQ-022 (column-level) | dbt tests | Block transform on critical failure |
| Post-transform | DQ-023 to DQ-028 (dataset-level) | dbt tests + Great Expectations | Block consumer access on critical failure |
| Hourly (continuous) | DQ-025 (freshness) | Custom SQL | Alert on failure |
| Weekly (audit) | All rules | Great Expectations | Generate quality report |
### Quality Report Template
| Metric | Value | Status |
|--------|-------|--------|
| Total rules executed | 28 | — |
| Rules passed | 26 | ✅ |
| Rules failed (critical) | 0 | ✅ |
| Rules failed (warning) | 2 | ⚠️ |
| Row count | 2,543,210 | ✅ |
| Null rate (order_id) | 0% | ✅ |
| Null rate (payment_method) | 12.3% | ⚠️ (expected for non-completed) |
| Duplicate rate | 0% | ✅ |
| Freshness (hours) | 2.5 | ✅ |
| Referential integrity | 100% | ✅ |
Explicación
Las reglas operan a dos niveles. Las reglas a nivel de columna (DQ-001 a DQ-022) verifican campos individuales y atrapan los fallos frecuentes: nulos, duplicados, formatos incorrectos, valores fuera de rango. Las reglas a nivel de dataset (DQ-023 a DQ-028) verifican la tabla completa: cantidad de filas, frescura, integridad referencial y consistencia entre tablas. Un pipeline puede pasar todas las reglas de columna y aun así publicar datos viejos o vacíos; por eso existe el nivel de dataset.
La severidad define qué pasa cuando una regla falla. Un fallo crítico bloquea el pipeline para que el dato malo nunca llegue a los consumidores. Un warning registra el problema y deja continuar la ejecución, lo que cubre violaciones inusuales pero legítimas, como un monto de orden por encima del rango normal. La división importa más de lo que parece: los equipos que marcan todo como crítico terminan silenciando las alertas al tercer falso positivo, y a partir de ahí las reglas existen solo en el papel.
El siguiente esquema muestra dónde corre cada grupo de reglas dentro de un pipeline batch típico:
Los checks de columna corren justo después de la carga a staging, antes de que cualquier transformación gaste cómputo en una entrada defectuosa. Los checks de dataset corren después de la transformación, sobre la forma final de los datos. La frescura corre en su propio esquema horario porque el envejecimiento puede ocurrir entre ejecuciones del pipeline, no solo durante ellas.
Sobre las herramientas: los tests de dbt están basados en SQL, viven junto a los modelos y corren como parte de dbt build, así que son la opción por defecto para los checks estándar. Great Expectations está basado en Python y funciona mejor para reglas condicionales (como “payment_method requerido solo cuando status es completed”) y para generar reportes de auditoría que un no ingeniero puede leer. Correr ambos es normal; el solapamiento cuesta poco y cada uno cubre lo que al otro le cuesta.
Derivar las reglas de un data contract es el punto de partida práctico. Cada “debe” del contrato se convierte en una regla: “order_id es obligatorio” se convierte en DQ-001, “los montos deben cuadrar con los ítems” se convierte en DQ-017. Cuando una regla no tiene contrato detrás, anota igual la razón de negocio. Las reglas sin razón declarada son las que nadie puede defender cuando empiezan a fallar, y terminan borradas en vez de corregidas.
Mantén las reglas versionadas junto al esquema que protegen. Una columna renombrada o un nuevo valor de enum rompe reglas en silencio si viven fuera del control de versiones, y el modo de fallo es de los peores: el check deja de correr y nadie se entera hasta que un consumidor se queja. En dbt esto sale gratis porque los tests viven en el YAML del esquema junto al modelo. Con SQL independiente o Great Expectations, guarda las suites en el mismo repositorio que el código del pipeline y revisa los cambios en conjunto.
Variantes
| Contexto | Enfoque | Notas |
|---|---|---|
| Pipeline de streaming | Usar checks de ventana deslizante | Reemplazar checks de batch por agregados por ventana de tiempo de evento |
| Feature store de ML | Añadir checks de distribución de features | Detectar drift de datos y cambios de esquema antes de reentrenar |
| Datos de compliance | Añadir detección de PII y checks de enmascaramiento | Requisitos de GDPR y CCPA |
| Datos financieros | Reglas de exactitud más estrictas | Cada centavo debe cuadrar; tratar los warnings como fallos |
| Contenido generado por usuarios | Añadir checks de calidad de contenido | Profanidad, spam, problemas de encoding |
Para validación a nivel de DataFrame fuera del warehouse, la receta sobre validar schemas de DataFrame con Pandera aplica la misma idea de reglas dentro del código Python en lugar de SQL.
Qué Funciona
Empieza con el conjunto pequeño de reglas que atrapan los fallos catastróficos: not null en claves primarias, unique en identificadores, integridad referencial en claves foráneas y un recuento de filas mayor a cero. Esas cinco o seis reglas previenen la mayoría de los desastres; todo lo demás es refinamiento.
Usa warnings para los casos de borde en lugar de exigir un 100% de estrictud. Una regla que bloquea el pipeline porque tres filas de dos millones tienen un método de pago inesperado será desactivada en un mes. Regístrala, revísala semanalmente y promuévela a crítica solo cuando la violación sea genuinamente imposible.
Corre las reglas dentro del pipeline en lugar de hacerlo como una auditoría separada. Un reporte posterior te dice que el dato malo ya llegó al dashboard; un check dentro del pipeline evita que llegue.
Sigue las métricas de calidad en el tiempo, no solo el pass/fail. Una tasa de nulos que sube de 0.1% a 3% en dos semanas es una señal temprana de que un sistema de origen cambió algo, mucho antes de que cualquier regla dispare su umbral.
Anota la razón de negocio de cada regla (“¿por qué importa esto?”) y revisa la suite cada trimestre. Los esquemas y la lógica de negocio cambian, y las reglas que protegían el esquema del año pasado hoy no protegen nada. Por último, alerta los fallos como corresponde: una regla que falla en silencio en un log que nadie lee da una confianza falsa, que es peor que no tener regla alguna.
Errores Comunes
No tener reglas de calidad, con la intención de “revisarlo manualmente”. Las revisiones manuales nunca ocurren a las 3 AM cuando se rompe el feed upstream.
Marcar todas las reglas como críticas. Cuando cien reglas pueden bloquear el pipeline, el equipo aprende a ignorar los fallos y la etiqueta de crítico pierde su sentido.
Escribir reglas que registran fallos pero no disparan ninguna acción. Si nadie recibe una alerta y ninguna ejecución se bloquea, la regla es decoración.
Dejar las reglas sin versionar. El esquema cambia, la regla sigue consultando la columna vieja, deja de coincidir con filas en silencio, y el equipo cree que los datos se siguen verificando.
Saltarse el check de frescura. Los datos viejos pasan todas las demás reglas y se ven perfectamente sanos; solo un check explícito de actualidad atrapa un feed que dejó de llegar hace dos días.
Definir reglas demasiado estrictas para los datos reales. Exigir 100% de completitud en campos genuinamente opcionales bloquea filas válidas y entrena a todos a ignorar los checks.
Reglas sin documentar. Cuando una regla falla y nadie recuerda por qué existe, se elimina en vez de investigarse, y la protección que daba desaparece con ella.
Ver También
- Plantilla de Documento de Diseño de Data Pipeline para documentar el pipeline que estas reglas protegen.
- Plantilla de Runbook para Jobs ETL para el lado operativo de correr el pipeline.
- Plantilla de Política de Gobernanza de Datos para la capa de política por encima de las reglas individuales.
- Guía de Data Quality para profiling, monitoreo y manejo de incidentes alrededor de estos checks.
- Documentación de data tests de dbt para la sintaxis completa de tests usada en la sección YAML.
- Documentación de Great Expectations para checkpoints y para extender la suite de ejemplo.
Código companion: recursos de reglas de calidad de datos: la plantilla en blanco, el schema de dbt y los tests personalizados, y la suite de Great Expectations de esta página.
Preguntas frecuentes
¿Cuántas reglas de calidad deberíamos tener?
Empieza con 5-10 reglas críticas por dataset: not null en claves primarias, unique en identificadores, integridad referencial en claves foráneas y un recuento de filas mayor a cero. Añade reglas de warning a medida que descubras casos de borde. Un dataset maduro suele tener 20-30 reglas. Más reglas significan más mantenimiento y más falsos positivos, así que haz crecer la suite solo cuando aparezca un nuevo modo de fallo.
¿Cuál es la diferencia entre severidad crítica y warning?
Las reglas críticas bloquean el pipeline: los datos no llegan a los consumidores si la regla falla. Las reglas de warning registran el problema pero permiten que la ejecución continúe. Usa crítico para reglas que indican datos rotos (clave primaria nula, registros duplicados) y warning para reglas que marcan datos inusuales pero posibles (un monto de orden muy alto, registros más viejos de lo habitual).
¿Deberíamos usar tests de dbt o Great Expectations?
Ambos, para trabajos distintos. Los tests de dbt están basados en SQL y se integran con el pipeline, así que úsalos para los checks estándar (not null, unique, relationships). Great Expectations está basado en Python y genera reportes detallados, así que úsalo para reglas condicionales y reportes de auditoría. Se complementan y los equipos suelen correrlos en paralelo.
¿Cómo manejamos reglas que fallan de forma intermitente?
Un fallo intermitente significa que la regla es demasiado estricta o que los datos tienen un problema de calidad que va y viene. Investiga primero el patrón: ¿se correlaciona con una fuente específica, una ventana de tiempo o un deploy upstream? Si la regla es demasiado estricta, bájala de crítica a warning o ajusta el umbral. Si los datos tienen un problema real, corrige el origen y conserva la regla.
¿Cómo medimos la calidad de datos en el tiempo?
Sigue la tasa de reglas que pasan, la tasa de nulos por columna, la tasa de duplicados, el lag de frescura y la varianza del recuento de filas en un dashboard. Las tendencias en degradación apuntan a problemas del sistema de origen, bugs del pipeline o drift de esquema. Alerta sobre cambios de tendencia y no solo sobre umbrales absolutos, porque un declive lento llega al mismo lugar malo que una rotura súbita, solo que más tarde.
¿Quién debería ser dueño de las reglas de calidad?
El equipo dueño del dataset, con aporte de los consumidores que sufren cuando se rompe. Los productores saben cómo deberían verse los datos; los consumidores saben qué fallos importan más. Dashboards compartidos y una revisión trimestral mantienen honestos a ambos lados.
Recursos Relacionados
Guía de Data Quality
Dominá data quality: frameworks de validación, profiling, schema enforcement, anomaly detection y monitoreo con Great Expectations, Pandera y Soda para pipelines confiables.
RecipeTransformar datos en el warehouse con dbt
Cómo usar dbt para transformaciones de datos en SQL con modelos, tests, materializaciones, macros y carga incremental en un data warehouse.
RecipeValidar schemas de DataFrame con Pandera
Cómo validar schemas de DataFrames de pandas y Polars con Pandera: tipos de columnas, constraints, checks personalizados, hypothesis testing y herencia de schemas.
DocPlantilla de Documento de Diseño de Data Pipeline
Una plantilla para documentar sources, transforms, sinks, scheduling, error handling y monitoring de data pipelines con schema definitions.
DocPlantilla de Runbook para Jobs ETL
Un runbook para operar, monitorear y troubleshootear jobs ETL: startup, shutdown, health checks, common failures, diagnostics y recovery.
DocPlantilla de Política de Gobernanza de Datos
Una plantilla para clasificación, retención, control de acceso, privacidad y cumplimiento de datos cubriendo GDPR, CCPA y SOC 2.