Pular para o conteúdo

Data contract no dbt: como impedir que o pipeline quebre em silêncio

· dbt, data contract, qualidade de dados

Em resumo: um data contract declara a forma que uma tabela promete entregar — colunas, tipos e restrições. No dbt, você liga isso no modelo (contract: enforced: true). Aí, quando o dado sai do combinado, o build falha na hora — antes de o erro virar relatório, antes de alguém decidir algo em cima de número torto. Falha cedo e falha alto. É a maneira mais direta de trocar a falha silenciosa por um erro que você vê no mesmo dia.

O que é um data contract?

É um acordo explícito sobre o formato de uma tabela: quais colunas existem, de que tipo são, o que pode ser nulo e o que precisa ser único. Sem contrato, cada consumidor adivinha. Cada um monta a sua versão da verdade e torce para a fonte não mexer em nada. Com contrato, o formato é lei — e quem quebra a lei é barrado na entrada, não descoberto no fechamento.

O problema que ele resolve é o mais perigoso de todos. Não é o pipeline que quebra: é o que completa sem erro e entrega número errado. Uma fonte muda um tipo, o autodetect decide sozinho, uma coluna some, e o build roda verde porque ninguém nunca disse a ele o que era "certo". Verde não quer dizer correto.

Como o dbt implementa isso (model contracts)

O dbt tem contratos de modelo nativos. Você declara colunas e tipos no YAML e ativa o contrato. Na hora de materializar, o dbt confere a estrutura do SELECT contra tudo o que você prometeu — coluna por coluna, tipo por tipo. Bateu, grava. Não bateu, ele para o build com erro claro, em vez de gravar dado fora de forma.

models:
  - name: fct_transactions
    config:
      contract:
        enforced: true
    columns:
      - name: transaction_id
        data_type: string
        constraints:
          - type: not_null
      - name: amount
        data_type: numeric        # dinheiro é numeric, nunca float
        constraints:
          - type: not_null
      - name: created_at
        data_type: timestamp

Repare no amount como numeric. O contrato também é onde você crava o tipo do dinheiro — e impede que um autodetect distraído o transforme em float e comece a somar centavo errado três meses depois, quando o estrago já está espalhado no fechamento. Dinheiro nunca é float.

Uma precisão que evita frustração: o contrato sempre impõe o shape — nome e tipo das colunas — e o build falha se divergir. Já as constraints como not_null dependem do banco. O Postgres impõe todas; o Snowflake, só not_null; o BigQuery e o Databricks declaram, mas não impõem (fica como metadado). Trave a forma com o contrato; para as regras de valor, combine com testes.

Contract-first: o contrato antes do dado

O ganho maior vem de inverter a ordem. Escreva o contrato primeiro e construa o modelo para cumpri-lo. Assim, o formato da camada que o BI consome (a Gold) vira uma decisão de projeto, não um acidente do que a fonte mandou hoje de manhã. O relatório passa a depender de um formato estável e auditável, e qualquer mudança de origem esbarra no contrato antes de contaminar a saída. A ordem muda tudo.

Num pipeline antifraude que montei, a camada Gold ficou 100% sob contrato. Quando uma fonte mudava um tipo, o build passava a falhar na hora — não virava relatório errado no fechamento. E isso deixou de ser modismo: existe um padrão aberto, o ODCS (Open Data Contract Standard), hoje sob a Linux Foundation, e capital entrando no tema — a Gable levantou US$ 20 mi de série A para o movimento shift-left. O próprio dbt segue a onda com a engine Fusion, em Rust e com lineage em nível de coluna.

E quando o schema muda mesmo?

Contrato barra o que quebra a forma na materialização. Só que ele não te avisa sozinho que a origem mudou — ele reage, não vigia. Combine com duas coisas:

  • Monitorar mudança de schema na entrada, para saber que a fonte mudou de layout assim que acontece.
  • Quarentena para as linhas que violam regra: segurá-las e sinalizá-las em vez de deixá-las passar ou sumir.

Contrato (a forma é lei), monitor (a origem mudou) e quarentena (o que não presta fica visível) são as três camadas de um pipeline que quebra alto, não em silêncio.

Perguntas frequentes

Preciso reescrever meu pipeline para usar data contract? Não. Você começa por um modelo só — em geral a tabela Gold que o BI mais consome. Declara as colunas, liga enforced: true, roda. O resto do pipeline continua igual. Contrato é incremental por natureza: um modelo hoje, o próximo na semana que vem, sem parar nada para isso.

Data contract substitui os testes do dbt? Não, e nem tenta. Os dois cobrem coisas diferentes. O contrato garante a forma — colunas, tipos, o que é not null — na hora de materializar; os testes checam o conteúdo, coisas como "esse valor está no intervalo esperado?" ou "essa chave é mesmo única nos dados?". Um trava a estrutura, o outro examina os números. Você quer os dois.

Funciona para quem não usa dbt? O contract: enforced: true é do dbt. Mas a ideia — declarar a forma e barrar quem sai dela — não depende de ferramenta nenhuma. Dá para fazer com validação de schema no código, com constraints no próprio banco ou com uma camada de qualidade na entrada. Sem dbt, o mecanismo muda; o princípio, não.

Implemento isso em pipelines ETL/ELT. Se o seu pipeline "roda bem" mas o número às vezes vem errado, o contrato é o primeiro lugar onde eu olho.

Leia também

Peça um diagnóstico do seu fechamento

Deixe seu contato e eu retorno com uma leitura rápida de onde seu relatório depende de uma pessoa — sem compromisso.

Resposta humanaSem cobrança até a propostaNDA bilateral

Esse problema parece o seu?

Uma conversa de 30 minutos, sem compromisso. Eu falo onde está o risco e o que resolver primeiro.