Brains Up AnalyticsBRAINSUPAnalytics
DatabricksLakeflowData QualityUnity CatalogPySpark

Expectations no Lakeflow: qualidade de dados como código, governada no Unity Catalog

Como declarar regras de qualidade ao lado da transformação, escolher entre registrar, descartar ou falhar, e governar tudo pelo Unity Catalog com regras versionadas e auditáveis.

Por Dione Fraga · Databricks Certified Professional22 de agosto de 20265 min de leitura

Na maioria dos pipelines que herdo, a "qualidade de dados" é um script que roda depois da carga: uma bateria de SELECT COUNT(*) WHERE campo IS NULL que alguém abre na segunda-feira e, quando encontra problema, o dado ruim já foi consumido por três dashboards e um modelo. É reação, não prevenção.

As Expectations do Lakeflow (as Databricks Declarative Pipelines, evolução do antigo DLT) invertem essa lógica. A regra de qualidade passa a viver ao lado da transformação, como código versionado, e o Unity Catalog governa, audita e reaproveita essa regra entre pipelines. Neste artigo eu mostro o conceito, o código na prática e por que isso importa para quem opera dados em produção.

O conceito: qualidade como contrato, não como verificação

Uma Expectation é uma restrição declarativa sobre um dataset de um pipeline — uma materialized view, uma streaming table ou uma view temporária. Você descreve, em SQL booleano, o que significa um registro válido e diz ao pipeline o que fazer quando a condição não é satisfeita.

A diferença de mentalidade é a palavra contrato. Em vez de "vou checar depois se veio nulo", você declara "esta tabela não aceita CPF nulo" e o mecanismo cuida do resto — inclusive de registrar quantos registros violaram a regra, para você medir a saúde da fonte ao longo do tempo.

O código na prática

O ponto de entrada em 2026 é o módulo pipelines do PySpark. Você importa, decora a função que produz a tabela e anexa a expectation:

from pyspark import pipelines as dp

@dp.table()
@dp.expect_or_drop("cpf_valido", "cpf IS NOT NULL")
def clientes():
    return spark.readStream.table("bronze.clientes_raw")

Três elementos aqui:

  • @dp.table() declara que a função materializa uma tabela do pipeline.
  • @dp.expect_or_drop(...) anexa a regra. O primeiro argumento é o nome da expectation (aparece nas métricas), o segundo é a condição SQL que um registro válido precisa satisfazer.
  • A função retorna a query — o Spark cuida do plano de execução.

Os 6 decorators e quando usar cada um

O módulo oferece seis decorators, organizados por o que acontece com a violação e por quantidade de regras.

Regra única:

  • @dp.expectregistra e mantém a linha (monitorar).
  • @dp.expect_or_dropdescarta a linha ruim.
  • @dp.expect_or_failinterrompe o pipeline.

Múltiplas regras (dicionário):

  • @dp.expect_all — registra e mantém.
  • @dp.expect_all_or_drop — descarta.
  • @dp.expect_all_or_fail — interrompe.

A escolha é uma decisão de negócio, não de código:

  • expect — use quando quer observabilidade sem bloquear. Ideal para começar: você mede a taxa de violação de uma fonte nova antes de decidir barrar.
  • expect_or_drop — use quando a linha ruim não pode chegar ao consumo, mas o pipeline pode seguir com o restante. É o caso mais comum em camadas silver/gold.
  • expect_or_fail — use para invariantes críticas de negócio (ex.: chave primária duplicada, valor monetário negativo onde é impossível). Falhar cedo é mais barato que propagar.

Múltiplas regras de uma vez

Para validar várias condições, use as variantes _all, passando um dicionário nome -> condição:

regras = {
    "cpf_valido":     "cpf IS NOT NULL",
    "idade_plausivel":"idade BETWEEN 0 AND 120",
    "uf_preenchida":  "uf IS NOT NULL",
}

@dp.table()
@dp.expect_all_or_drop(regras)
def clientes():
    return spark.readStream.table("bronze.clientes_raw")

Com expect_all_or_drop, um registro é descartado se falhar em qualquer das regras. Cada regra continua sendo medida individualmente nas métricas — você sabe qual condição está derrubando os dados.

O salto de 2026: regras governadas pelo Unity Catalog

Historicamente, as expectations viviam presas ao código do pipeline. A novidade que muda o jogo é poder armazenar e gerenciar as regras de qualidade dentro de tabelas do Unity Catalog. Na prática, isso traz três benefícios diretos:

  1. Versionamento e auditoria — a regra deixa de ser uma linha perdida em um notebook e passa a ser um objeto governado, com histórico. Auditoria e compliance conseguem responder "qual regra estava valendo em março?".
  2. Reutilização entre pipelines — a mesma definição de "cliente válido" pode ser referenciada por vários pipelines, em vez de copiada e colada (e divergindo com o tempo).
  3. Governança centralizada — junto com a propagação automática de permissões MANAGE para materialized views e streaming tables no Unity Catalog, a qualidade entra no mesmo perímetro de governança do resto dos dados.

Some a isso outras evoluções recentes do Lakeflow que tornam o padrão mais robusto em produção: testes unitários em Python direto no editor de pipelines (validando a lógica contra dados mockados por redirecionamento de tabela), type widening para evoluir tipos de coluna sem reset de pipeline, e modo de execução em fila que enfileira updates concorrentes em vez de falhar por conflito.

Por que isso importa

Quando a qualidade vira código declarativo e governado, três coisas mudam para o time:

  • Dados confiáveis sem vigiar a carga. A regra roda toda execução; a violação é registrada automaticamente. Ninguém precisa abrir o painel na segunda de manhã.
  • Decisão explícita de risco. expect / drop / fail obrigam o time a decidir, para cada regra, o custo de deixar passar versus o custo de barrar. Isso documenta o apetite de risco no próprio pipeline.
  • Observabilidade nativa. As métricas de qualidade fazem parte do pipeline — dá para acompanhar a taxa de violação por fonte ao longo do tempo e agir antes que vire incidente.

Como começar amanhã

  1. Escolha uma tabela silver crítica e liste 3 a 5 invariantes que você sabe que deveriam valer.
  2. Comece com @dp.expect (só monitorar) por alguns dias para medir a taxa real de violação — evita descartar dado bom por uma regra mal calibrada.
  3. Promova as regras estáveis para expect_or_drop; reserve expect_or_fail para as poucas invariantes que justificam parar a carga.
  4. Quando o padrão amadurecer, mova as definições para o Unity Catalog e compartilhe entre pipelines.

Qualidade deixa de ser uma reação semanal e vira um contrato que o pipeline honra a cada execução. Na prática, é o tipo de mudança que costuma pagar dividendos mais rápido do que quase qualquer otimização de performance — porque evita o retrabalho silencioso de reprocessar dado ruim já consumido.

Artigos relacionados

Gostou? Veja os e-books para conteúdo aprofundado.

E-books