¿Qué es un contrato de datos? Una definición práctica

Qué es un contrato de datos, qué contiene realmente, en qué se diferencia de un esquema o de un SLA y cómo se hace cumplir, con un ejemplo resuelto en ODCS.

· 8 min read

Un contrato de datos es un acuerdo explícito y versionado entre quien produce un dataset y quienes lo consumen, que especifica qué garantiza ese dataset: su esquema, el significado de cada campo, las expectativas de calidad de datos que debe cumplir y los niveles de servicio —frescura, disponibilidad, soporte— bajo los que se entrega. Se escribe como un documento legible por máquina, se guarda en control de versiones junto al código, se revisa mediante pull requests y se hace cumplir automáticamente ejecutando sus expectativas de calidad contra los datos reales. Un contrato es una promesa sobre una interfaz, no la descripción de un pipeline.

La palabra “contrato” trabaja de verdad en esa definición. Implica dos partes con nombre, una obligación declarada, una versión a la que se puede apuntar y consecuencias cuando la obligación no se cumple. Un archivo de esquema no tiene ninguna de esas propiedades; un contrato tiene las cuatro.

Por qué surgieron los contratos de datos

Tres modos de fallo llevaron a los equipos hasta esta idea, y conviene nombrarlos porque explican la forma de la solución.

Deriva de esquema sin aviso. Un equipo productor renombra una columna, amplía un tipo o elimina un campo que cree que nadie usa. El cambio pasa sus tests, porque sus tests cubren su código. Aguas abajo se rompe un dashboard, un modelo se reentrena en silencio sobre nulos o un job nocturno falla a las 03:00. No había interfaz, así que no había nada que romper: solo una tabla que cambió.

Dashboards rotos sin un responsable. Cuando la calidad se degrada, la conversación empieza con arqueología. ¿Quién produce esta tabla? ¿Qué se suponía que debía contener? ¿Un 4 % de nulos en customer_id siempre fue normal? Nadie lo escribió, así que la respuesta tarda una semana y el arreglo es un parche aguas abajo en lugar de aguas arriba.

Acoplamiento entre productor y consumidor. Sin una interfaz declarada, los consumidores hacen ingeniería inversa de la implementación del productor: leen tablas intermedias, dependen de ordenaciones accidentales, codifican a fuego suposiciones sobre los valores de un campo de estado. Cada una de esas cosas se convierte en una obligación no escrita que el productor ni siquiera sabe que tiene.

La industria del software resolvió el problema análogo con los contratos de API: especificaciones OpenAPI, versionado semántico, ventanas de deprecación. Un contrato de datos aplica la misma disciplina en la interfaz de datos. La idea central es que la promesa en sí pasa a ser un artefacto, separado del pipeline que la cumple y separado de la herramienta que la comprueba.

Qué contiene un contrato de datos

Un contrato completo recoge cinco cosas.

  1. Identidad y propiedad. Qué es el dataset, qué equipo lo posee, cómo contactar con él y cuál es la versión del propio contrato. La propiedad no es decorativa: es la parte que está al otro lado del acuerdo.
  2. Esquema y semántica. Los campos, sus tipos (lógicos y físicos), si son obligatorios y —esto es lo decisivo— qué significa cada uno. amount no es una descripción; “total del pedido en EUR, sin IVA, después de descuentos” sí lo es.
  3. Expectativas de calidad. Las reglas que los datos deben satisfacer, cada una con un umbral y una severidad: las columnas obligatorias nunca son nulas, las claves son únicas, los campos categóricos se mantienen dentro de un conjunto permitido, los números se mantienen dentro de un rango plausible, las claves foráneas resuelven.
  4. Niveles de servicio. Frescura (con qué antelación deben haberse actualizado los datos), disponibilidad, retención y las expectativas de soporte que las acompañan.
  5. Política de cambios. Cómo se versiona el contrato, qué cuenta como cambio rompedor y con cuánta antelación se avisa a los consumidores antes de que aterrice uno.

Así es la forma en la práctica, escrita en el Open Data Contract Standard:

apiVersion: v3.0.0
kind: DataContract
info:
  title: orders
  version: 2.1.0
  owner: data-platform
schema:
  - name: orders
    physicalName: orders
    physicalType: table
    properties:
      - name: order_id
        logicalType: string
        physicalType: uuid
        required: true
        primaryKey: true
        description: Business key, stable across restatements.
        quality:
          - rule: nullCount
            dimension: completeness
            severity: error
            mustBe: "0"
          - rule: duplicateCount
            dimension: uniqueness
            severity: error
            mustBe: "0"
      - name: status
        logicalType: string
        description: Lifecycle state. New values require a minor version bump.
        quality:
          - rule: validValues
            dimension: conformity
            severity: error
            mustBe: "['pending', 'paid', 'shipped', 'refunded']"
      - name: total_amount
        logicalType: number
        physicalType: numeric
        description: Order total in EUR, excluding VAT, after discounts.
        quality:
          - rule: between
            dimension: accuracy
            severity: error
            mustBe: "[0, 100000]"
      - name: created_at
        logicalType: timestamp
        quality:
          - rule: freshness
            dimension: timeliness
            severity: error
            mustBe: "<= 24h"

Léelo como una frase: el equipo data-platform promete una tabla llamada orders, cuyo order_id está siempre presente y es único, cuyo status es uno de exactamente cuatro valores, cuyo total_amount es una cifra en euros entre cero y cien mil, y que nunca tiene más de 24 horas de antigüedad. Esa frase es el contrato. Todo lo demás es sintaxis.

Contratos, esquemas y SLA

Los tres se confunden a menudo, y las diferencias son justo lo que importa.

Contrato de datosEsquemaSLA
DeclaraEstructura, significado, calidad y niveles de servicioSolo estructura y tiposObjetivos de disponibilidad y actualidad
Tiene dos partesSí: productor y consumidores con nombreNoNormalmente
Versionado como artefactoSí, semánticamente, en gitA vecesRara vez
Exigible por softwareSí, mediante un runner de validaciónEn parte, en el momento de la escrituraSe mide, no se exige
Cubre la semánticaNoNo

Un esquema te dice que una columna es un string. Un contrato te dice que es un código de moneda, que siempre es uno de los valores ISO 4217 que aceptas, que nunca es nulo y que el equipo de pagos responde por él. Un SLA te dice que la tabla se refresca a diario; un contrato declara eso y además qué tiene que ser cierto de las filas que contiene.

Dicho de forma sencilla: un esquema es un subconjunto de un contrato, y un SLA es un subconjunto de un contrato. El contrato es el artefacto que hace ambos revisables en un mismo sitio.

Cómo se hacen cumplir los contratos

Un contrato que nadie comprueba es un documento, no un acuerdo. El cumplimiento se aplica en tres momentos.

En la revisión. Como el contrato es un archivo, un cambio en él es un diff en un pull request con un autor y un motivo. Esta es la propiedad más valiosa y menos comentada de los contratos de datos: alguien puede discutir un umbral antes de que se fusione. Una regla relajada en la interfaz de un proveedor no deja rastro de si cambió el negocio o de si alguien se cansó de la alerta.

En la ejecución. Un runner compila cada expectativa de calidad en una consulta contra el dataset real y registra el resultado. nullCount se convierte en un COUNT(*) WHERE col IS NULL; freshness se convierte en una comparación contra now(). Esto es validación de datos del montón: el contrato es simplemente el lugar donde se declaran las expectativas en vez de estar dispersas por varios scripts, y la guía para validar datos explica cómo se escriben, se programan y se les fija umbral a esas consultas en la práctica. La severidad decide la consecuencia: error bloquea o alerta, warning registra una tendencia.

En el cambio. El versionado semántico del contrato es lo que transporta el significado. Un patch relaja o endurece un umbral; una minor añade una columna o una regla, de forma aditiva; una major elimina o renombra un campo, cambia un tipo o empieza a rechazar datos que antes se aceptaban. La versión es lo que permite a un consumidor decidir si un cambio le afecta sin tener que leerse el diff.

Catalyst implementa exactamente este bucle: los contratos son YAML de ODCS con el archivo como fuente de la verdad, las reglas se compilan al SQL nativo de cada motor en PostgreSQL, BigQuery, SQL Server y otros, y los resultados se agregan por dimensión de calidad para que los huecos de cobertura se vean en lugar de quedar implícitos.

Por dónde empezar

No empieces contratando todo. Elige un dataset que haya roto algo hace poco y que tenga un propietario identificable, escribe lo que ya promete de forma implícita y consigue que el productor lo acepte. Importa el esquema desde la base de datos en lugar de teclearlo: un borrador generado de treinta reglas que luego podas es un punto de partida mucho mejor que un archivo en blanco.

El primer contrato es un ejercicio de documentación. El segundo es donde la disciplina empieza a rentar, porque para entonces alguien habrá intentado meter un cambio rompedor y el contrato lo habrá detenido.

Preguntas frecuentes

¿Qué es un contrato de datos en palabras sencillas?

Un contrato de datos es un acuerdo escrito y versionado sobre lo que garantiza un dataset: qué campos tiene, qué significan, qué reglas de calidad deben cumplir y con qué frescura llegarán los datos. Se guarda en control de versiones como si fuera código, se revisa en pull requests y se comprueba automáticamente contra los datos reales.

¿Cuál es la diferencia entre un contrato de datos y un esquema?

Un esquema describe la estructura: nombres de campos y tipos. Un contrato de datos incluye el esquema, pero añade lo que un esquema no puede expresar: qué significa cada campo, las reglas de calidad que los valores deben satisfacer, los niveles de servicio de frescura y disponibilidad, el propietario responsable y una política de versionado que dice qué cuenta como cambio rompedor.

¿Son lo mismo los contratos de datos y ODCS?

No. “Contrato de datos” es el concepto: una promesa acordada y versionada entre un productor y sus consumidores. ODCS, el Open Data Contract Standard, es un formato abierto y neutral respecto a proveedores para escribir esa promesa en YAML. Puedes tener contratos de datos en un formato propio; usar un estándar abierto es lo que los mantiene portables entre herramientas.

¿Cómo se hace cumplir un contrato de datos?

Compilando sus expectativas de calidad en consultas que se ejecutan de forma programada contra el dataset real, y revisando los cambios del propio contrato como pull requests. Las reglas llevan una severidad, así que un incumplimiento o bien bloquea el consumo aguas abajo o bien se registra como una tendencia de advertencia. Hacerlo cumplir es validación de datos corriente; el contrato es solo el lugar donde se declaran las expectativas.

¿Quién escribe el contrato de datos, el productor o el consumidor?

El productor es su propietario, porque es la parte que hace la promesa, pero el primer borrador suele negociarse, ya que son los consumidores quienes saben de qué garantías dependen realmente. Un contrato escrito solo por los consumidores es una lista de deseos; uno escrito solo por los productores tiende a prometer únicamente lo que ya es fácil.