<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andre Luis Anastacio</title>
    <description>The latest articles on DEV Community by Andre Luis Anastacio (@ndrluis).</description>
    <link>https://dev.to/ndrluis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F765110%2F06fc5f42-fe31-44df-b69d-181d8de2ca4f.jpeg</url>
      <title>DEV Community: Andre Luis Anastacio</title>
      <link>https://dev.to/ndrluis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ndrluis"/>
    <language>en</language>
    <item>
      <title>[Jornada Databricks] 01 - Experiência de Desenvolvimento</title>
      <dc:creator>Andre Luis Anastacio</dc:creator>
      <pubDate>Sat, 26 Sep 2026 18:57:22 +0000</pubDate>
      <link>https://dev.to/ndrluis/jornada-databricks-01-experiencia-de-desenvolvimento-669</link>
      <guid>https://dev.to/ndrluis/jornada-databricks-01-experiencia-de-desenvolvimento-669</guid>
      <description>&lt;p&gt;A Jornada Databricks será uma série de artigos em que compartilho o que venho aprendendo no meu dia a dia com a ferramenta. O objetivo é consolidar meus aprendizados e experiências enquanto construo uma plataforma de dados utilizando o ecossistema da Databricks.&lt;/p&gt;

&lt;p&gt;Como este é o primeiro artigo, preciso contextualizar algumas escolhas que fiz e que se distanciam um pouco do fluxo padrão do Spark Declarative Pipelines ou Lakeflow Pipelines, como é chamado na Databricks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Atualmente, nossa plataforma de dados é construída em cima de um projeto dbt, utilizando Apache Iceberg como formato de tabela e Trino como query engine. Surgiu uma necessidade de negócio para que determinados processamentos fossem atualizados em janelas de 1 hora. Para o cenário tradicional de D-1, a arquitetura dbt + Trino sempre funcionou muito bem. Contudo, ao migrar para atualizações horárias, o desafio aumentou consideravelmente, pois o custo computacional de identificar o que mudou para aplicar uma carga incremental tornou-se maior do que simplesmente reprocessar a tabela inteira (full refresh).&lt;/p&gt;

&lt;p&gt;Acontece que reprocessar tabelas inteiras a cada hora gera um custo gigantesco de computação e armazenamento, além de fazer com que o uso de formatos com suporte a time travel traga desvantagens dado que os snapshots e versões antigas do Iceberg acumulam-se rapidamente como lixo, demandando um esforço operacional contínuo de manutenção.&lt;/p&gt;

&lt;p&gt;Atento a essa dor, eu já vinha acompanhando o SDP (Spark Declarative Pipelines), lançado no Spark 4.1 e derivado do DLT (Delta Live Tables, atual Lakeflow Pipelines). Ele parecia uma excelente alternativa por se basear no conceito de View Materializadas. No entanto, o SDP open source é apenas um Lakeflow Pipelines simplificado. Ele não possui suporte ao IVM (Incremental View Maintenance), recurso essencial para a nossa necessidade de atualização incremental eficiente.&lt;/p&gt;

&lt;p&gt;Por outros motivos estratégicos, a empresa onde trabalho optou por contratar a Databricks, o que acabou resolvendo essa e outras dores. Essa necessidade de reprocessamento horário não foi o principal causador da mudança, o motivador real foi o tamanho reduzido do nosso time (apenas 3 pessoas). Estava inviável manter uma infraestrutura 100% open source e, ao mesmo tempo, evoluir a plataforma. Para se ter uma ideia, mantínhamos internamente serviços como Trino, Trino Gateway, Starrocks, Cube, Superset, Lakekeeper, Airflow, OpenMetadata, dbt, Meltano e conectores do Kafka (Debezium e Iceberg Sink).&lt;/p&gt;

&lt;h2&gt;
  
  
  Primeiras dores
&lt;/h2&gt;

&lt;p&gt;A partir de agora, falarei especificamente do ecossistema Databricks, sem me aprofundar nas limitações da versão open source do SDP por ser bastante reduzida em comparação ao Lakeflow Pipelines.&lt;/p&gt;

&lt;p&gt;Logo de início, busquei entender como seria a esteira de desenvolvimento e percebi que não teríamos a construção automática de DAGs e a funcionalidade de Defer de maneira transparente, essas duas funcionalidades são essenciais para um fluxo de trabalho ágil e eficiente, principalmente tendo em vista que estamos construindo uma plataforma self-service, onde pessoas desenvolvedoras sem experiência com engenharia de dados terão que trabalhar.&lt;/p&gt;

&lt;p&gt;No Lakeflow Pipelines (LFP), a estrutura é organizada principalmente em torno de Pipelines. Existem regras e limitações específicas, uma delas é que cada Pipeline suporta no máximo 16 Flows concorrentes, essa é uma limitação que não é documentada. &lt;/p&gt;

&lt;p&gt;Em uma DAG tradicional do dbt, encadeamos todos os recursos (tabelas, views e MVs) de forma contínua, sem essa limitação. No LFP, portanto, precisamos planejar melhor quais recursos residem em cada Pipeline e o seu escopo.&lt;/p&gt;

&lt;p&gt;Porém, nossa equipe estava habituada a uma experiência de desenvolvimento em que a pessoa não precisa se preocupar em como a DAG será montada. Bastava declarar os relacionamentos entre tabelas via aliases (como ref e source no dbt) e a DAG era gerada de forma transparente no Airflow via Astronomer Cosmos.&lt;/p&gt;

&lt;p&gt;Vale abrir um parêntese, embora seja viável utilizar o dbt integrado à Databricks, essa abordagem geraria MVs isoladas (standalone). Consequentemente, cada Materialized View demandaria sua própria pipeline dedicada e a alocação de uma nova instância serverless, elevando consideravelmente o custo computacional. Além disso, a execução da atualização ocorre por meio de um SQL Warehouse, criando uma cobrança duplicada. Para contornar essa proliferação de pipelines, a alternativa seria recorrer à estratégia de cargas incrementais no padrão do dbt, o que nos levaria exatamente de volta ao problema inicial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mason - Nosso ‘clone” do DBT para a Databricks
&lt;/h2&gt;

&lt;p&gt;Para resolver essa lacuna, criamos o Mason, nossa própria CLI. Com o auxílio de LLMs na escrita de código, desenvolvemos a primeira versão funcional em apenas duas semanas e, ao longo das duas semanas seguintes, refinamos e adicionamos funcionalidades à ferramenta.&lt;/p&gt;

&lt;p&gt;Atualmente, o Mason reproduz com fidelidade o que o dbt faz de melhor, além de agregar melhorias próprias. Não entrarei no detalhe de cada funcionalidade desenvolvida agora, pois trarei esses detalhes em edições futuras da Jornada.&lt;/p&gt;

&lt;p&gt;Neste primeiro momento, basta saber que resolvemos tanto a funcionalidade de Defer quanto a construção automática de DAGs para o encadeamento entre Pipelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definição dos Flows e construção de Pipelines
&lt;/h2&gt;

&lt;p&gt;A única configuração necessária é a declaração da fonte (Source). De forma bem parecida com o dbt, utilizamos um arquivo YAML onde especificamos a origem da tabela, permitindo que a CLI construa as referências automaticamente.&lt;/p&gt;

&lt;p&gt;Exemplo de arquivo de source do Mason (&lt;code&gt;sources.yml&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vendas&lt;/span&gt;
    &lt;span class="na"&gt;tables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pedidos&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pedidos&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;realizados&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;na&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;plataforma"&lt;/span&gt;
        &lt;span class="na"&gt;identifier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pedidos_2&lt;/span&gt;   &lt;span class="c1"&gt;# nome físico da tabela no Unity Catalog caso você queira um nome diferente&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clientes&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cadastro&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;clientes"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por padrão, assumimos a leitura a partir do catálogo bronze, mas é possível sobrescrever o catálogo de origem se necessário.&lt;/p&gt;

&lt;p&gt;Em seguida, referenciamos a fonte em um dataset de limpeza inicial utilizando o prefixo src:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- datasets/silver/vendas/pedidos.sql&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;MATERIALIZED&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;pedidos&lt;/span&gt;
&lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="n"&gt;INCREMENTAL&lt;/span&gt;
&lt;span class="k"&gt;CLUSTER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;AUTO&lt;/span&gt;
&lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="s1"&gt;'Pedidos realizados na plataforma, uma linha por pedido, sem os excluídos na origem.'&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;                                  &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;pedido_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;cliente_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valor_total&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;valor_total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt;                          &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;pedido_criado_em&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;src_vendas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pedidos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;deleted_at&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- datasets/silver/vendas/clientes.sql&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;MATERIALIZED&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;clientes&lt;/span&gt;
&lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="n"&gt;INCREMENTAL&lt;/span&gt;
&lt;span class="k"&gt;CLUSTER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;AUTO&lt;/span&gt;
&lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="s1"&gt;'Cadastro de clientes, uma linha por cliente.'&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;cliente_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;src_vendas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clientes&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na sequência, construímos as tabelas fato ou dimensão utilizando a sintaxe de ref:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- datasets/gold/vendas/dim_cliente.sql&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;MATERIALIZED&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;dim_cliente&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;cliente_id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;nome&lt;/span&gt;       &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;uf&lt;/span&gt;         &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;regiao&lt;/span&gt;     &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;dim_cliente_pk&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cliente_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="n"&gt;INCREMENTAL&lt;/span&gt;
&lt;span class="k"&gt;CLUSTER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;AUTO&lt;/span&gt;
&lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="s1"&gt;'Clientes, uma linha por cliente, com os atributos usados para filtrar e agrupar os pedidos.'&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;cliente_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;uf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CASE&lt;/span&gt;
    &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'AC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'AM'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'AP'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'RO'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'RR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'TO'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Norte'&lt;/span&gt;
    &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'AL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'BA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'MA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PB'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PI'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'RN'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'SE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Nordeste'&lt;/span&gt;
    &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DF'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'GO'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'MS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'MT'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Centro-Oeste'&lt;/span&gt;
    &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ES'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'MG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'RJ'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'SP'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Sudeste'&lt;/span&gt;
    &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'PR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'RS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'SC'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Sul'&lt;/span&gt;
  &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;regiao&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ref_silver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vendas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clientes&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- datasets/gold/vendas/fct_pedido.sql&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;MATERIALIZED&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;fct_pedido&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;pedido_id&lt;/span&gt;        &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;cliente_id&lt;/span&gt;       &lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;data_do_pedido&lt;/span&gt;   &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;pedido_criado_em&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt;           &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;valor_total&lt;/span&gt;      &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fct_pedido_pk&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="n"&gt;INCREMENTAL&lt;/span&gt;
&lt;span class="k"&gt;CLUSTER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;AUTO&lt;/span&gt;
&lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="s1"&gt;'Pedidos, uma linha por pedido, com o valor e o cliente que comprou.'&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;pedido_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;cliente_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido_criado_em&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;data_do_pedido&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;pedido_criado_em&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;valor_total&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ref_silver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vendas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pedidos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um detalhe importante na sintaxe do ref é que exigimos a declaração explícita do schema. Essa foi uma mudança intencional em relação ao dbt, enquanto no dbt não é possível ter arquivos de modelos com o mesmo nome em schemas diferentes, com a nossa abordagem conseguimos dar suporte a nomes duplicados em schemas distintos de forma transparente.&lt;/p&gt;

&lt;p&gt;Após criar os arquivos SQL dos datasets, a pessoa desenvolvedora precisa apenas rodar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mason scaffold pipelines
resources/vendas__silver.pipeline.yml  criado
resources/vendas__silver.schema.yml    criado
resources/vendas__gold.pipeline.yml    criado
resources/vendas__gold.schema.yml      criado
resources/vars.mason.yml               criado
5 arquivo&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;, 5 alterado&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir disso, os arquivos de definição das Pipelines são gerados automaticamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GERADO por `mason scaffold pipelines`. Não editar à mão.&lt;/span&gt;
&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;vendas__silver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${var.run__name_prefix}vendas__silver"&lt;/span&gt;
      &lt;span class="na"&gt;catalog&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.dest__vendas__silver__catalog}&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.dest__vendas__silver__schema}&lt;/span&gt;
      &lt;span class="na"&gt;serverless&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;continuous&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="c1"&gt;# um arquivo por dataset do grupo silver/vendas&lt;/span&gt;
      &lt;span class="na"&gt;libraries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;glob&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;../datasets/silver/vendas/clientes.sql&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;glob&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;../datasets/silver/vendas/pedidos.sql&lt;/span&gt;
      &lt;span class="c1"&gt;# cada ${src_...} vira um parâmetro com o endereço físico do sources.yml&lt;/span&gt;
      &lt;span class="na"&gt;configuration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;src_vendas.clientes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.src__vendas__silver__vendas__clientes}&lt;/span&gt;
        &lt;span class="na"&gt;src_vendas.pedidos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.src__vendas__silver__vendas__pedidos}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GERADO por `mason scaffold pipelines`. Não editar à mão.&lt;/span&gt;
&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;vendas__gold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${var.run__name_prefix}vendas__gold"&lt;/span&gt;
      &lt;span class="na"&gt;catalog&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.dest__vendas__gold__catalog}&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.dest__vendas__gold__schema}&lt;/span&gt;
      &lt;span class="na"&gt;serverless&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;continuous&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="c1"&gt;# um arquivo por dataset do grupo gold/vendas&lt;/span&gt;
      &lt;span class="na"&gt;libraries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;glob&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;../datasets/gold/vendas/dim_cliente.sql&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;glob&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;../datasets/gold/vendas/fct_pedido.sql&lt;/span&gt;
      &lt;span class="c1"&gt;# cada ${ref_...} que aponta para outra pipeline vira um parâmetro aqui&lt;/span&gt;
      &lt;span class="na"&gt;configuration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;ref_silver.vendas.clientes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.ref__vendas__gold__silver__vendas__clientes}&lt;/span&gt;
        &lt;span class="na"&gt;ref_silver.vendas.pedidos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.ref__vendas__gold__silver__vendas__pedidos}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Linters
&lt;/h2&gt;

&lt;p&gt;Desenvolvemos também um conjunto de linters para garantir a qualidade, evitar erros comuns de desenvolvimento e dispensar a necessidade de verificação manual por parte das pessoas desenvolvedoras. Em cada artigo, destacarei os linters relevantes para os conceitos apresentados.&lt;/p&gt;

&lt;p&gt;Para o fluxo apresentado até aqui, estes são os principais linters ativos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fonte não declarada&lt;/strong&gt;: identifica quando uma definição de &lt;code&gt;src&lt;/code&gt; faz referência a uma tabela não mapeada no &lt;code&gt;sources.yml&lt;/code&gt; (ex: &lt;code&gt;${src_vendas.produtos}&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uso correto de src e ref&lt;/strong&gt;: restringe o uso de &lt;code&gt;src&lt;/code&gt; apenas à camada silver, impedindo que tabelas da camada gold leiam diretamente da bronze. As permissões de acesso entre camadas via &lt;code&gt;ref&lt;/code&gt; são estritamente validadas.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referência sem endereço completo&lt;/strong&gt;: bloqueia referências simplificadas no estilo do dbt (ex: &lt;code&gt;${ref_clientes}&lt;/code&gt;). É obrigatório especificar os três níveis (camada, schema e nome), o que viabiliza o uso do mesmo nome em schemas distintos. O linter indica os caminhos possíveis em caso de erro.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referência a dataset inexistente&lt;/strong&gt;: identifica referências quebradas e sugere nomes similares existentes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nome de recurso hardcoded&lt;/strong&gt;: impede referências diretas em SQL (ex: &lt;code&gt;FROM silver.vendas.pedidos&lt;/code&gt;), pois referências manuais não entram na construção da DAG de dependências.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependência cíclica&lt;/strong&gt;: detecta e exibe cadeias de dependência circulares antes da realização do deploy.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estrutura de arquivos&lt;/strong&gt;: valida se o dataset está localizado no diretório correto: &lt;code&gt;datasets/&amp;lt;camada&amp;gt;/&amp;lt;schema&amp;gt;/&amp;lt;arquivo&amp;gt;&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline desatualizada&lt;/strong&gt;: recalcula os arquivos de definição e compara com o conteúdo salvo no repositório. Alerta se alguém esquecer de rodar o comando &lt;code&gt;mason scaffold pipelines&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limite de 16 flows excedido&lt;/strong&gt;: indica quando um grupo ultrapassa o limite de 16 flows por Pipeline e fornece o comando para efetuar a divisão em sub-pipelines. Explicarei essa estratégia de divisão em publicações futuras.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As mensagens do linter são formatadas de forma orientativa para facilitar a correção:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mason lint
MASON-E002  datasets/silver/vendas/produtos.sql:12
            ${src_vendas.produtos} não está em sources.yml (schema vendas).
            Acrescente a tabela ao grupo do schema que a lê: é de lá que sai o
            endereço físico que o resolver emite.


1 achado(s).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;A transição para a Databricks aliviou a carga operacional de manter toda a infraestrutura com uma equipe reduzida, enquanto o Lakeflow Pipelines supriu a necessidade de atualizações incrementais que buscávamos no SDP. No entanto, sentimos falta da experiência de desenvolvimento ágil do dbt, essencial para sustentar nosso modelo de plataforma self-service.&lt;/p&gt;

&lt;p&gt;O Mason nasceu para preencher essa lacuna, a pessoa desenvolvedora escreve apenas o SQL, declara os arquivos de origem e utiliza os termos de referência (src e ref), deixando toda a orquestração e validação a cargo da CLI e dos linters. &lt;/p&gt;

&lt;p&gt;Embora criar e manter uma ferramenta própria exija esforço, com o advento das LLM's ficou fácil de implementar melhorias específicas para o nosso contexto e corrigir bugs sem depender de terceiros.&lt;/p&gt;

&lt;p&gt;Nos próximos artigos, falarei mais sobre o recurso de Defer, outras capacidades do Mason e as lições aprendidas ao lidar com cargas incrementais na prática.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Stack de onde partimos&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;dbt&lt;/strong&gt;: &lt;a href="https://docs.getdbt.com/" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;, &lt;a href="https://docs.getdbt.com/reference/dbt-jinja-functions/ref" rel="noopener noreferrer"&gt;&lt;code&gt;ref&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://docs.getdbt.com/reference/dbt-jinja-functions/source" rel="noopener noreferrer"&gt;&lt;code&gt;source&lt;/code&gt;&lt;/a&gt; e &lt;a href="https://docs.getdbt.com/reference/node-selection/defer" rel="noopener noreferrer"&gt;Defer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache Iceberg&lt;/strong&gt;: &lt;a href="https://iceberg.apache.org/" rel="noopener noreferrer"&gt;site&lt;/a&gt; e &lt;a href="https://iceberg.apache.org/docs/latest/maintenance/#expire-snapshots" rel="noopener noreferrer"&gt;manutenção e expiração de snapshots&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trino&lt;/strong&gt;: &lt;a href="https://trino.io/" rel="noopener noreferrer"&gt;site&lt;/a&gt; e &lt;a href="https://trinodb.github.io/trino-gateway/" rel="noopener noreferrer"&gt;Trino Gateway&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Starrocks&lt;/strong&gt;: &lt;a href="https://www.starrocks.io/" rel="noopener noreferrer"&gt;site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cube&lt;/strong&gt;: &lt;a href="https://cube.dev/" rel="noopener noreferrer"&gt;site&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache Superset&lt;/strong&gt;: &lt;a href="https://superset.apache.org/" rel="noopener noreferrer"&gt;site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lakekeeper&lt;/strong&gt;, catálogo REST do Iceberg: &lt;a href="https://docs.lakekeeper.io/" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache Airflow&lt;/strong&gt;: &lt;a href="https://airflow.apache.org/" rel="noopener noreferrer"&gt;site&lt;/a&gt; e &lt;a href="https://astronomer.github.io/astronomer-cosmos/" rel="noopener noreferrer"&gt;Astronomer Cosmos&lt;/a&gt;, que transforma o projeto dbt em DAG do Airflow
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenMetadata&lt;/strong&gt;: &lt;a href="https://open-metadata.org/" rel="noopener noreferrer"&gt;site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meltano&lt;/strong&gt;: &lt;a href="https://meltano.com/" rel="noopener noreferrer"&gt;site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kafka Connect&lt;/strong&gt;: &lt;a href="https://debezium.io/" rel="noopener noreferrer"&gt;Debezium&lt;/a&gt; e &lt;a href="https://iceberg.apache.org/docs/latest/kafka-connect/" rel="noopener noreferrer"&gt;Iceberg Sink Connector&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Spark Declarative Pipelines e Databricks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://spark.apache.org/docs/latest/declarative-pipelines-programming-guide.html" rel="noopener noreferrer"&gt;Spark Declarative Pipelines Programming Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.databricks.com/blog/bringing-declarative-pipelines-apache-spark-open-source-project" rel="noopener noreferrer"&gt;Bringing Declarative Pipelines to the Apache Spark Open Source Project&lt;/a&gt;, o anúncio da Databricks
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.databricks.com/aws/en/ldp/" rel="noopener noreferrer"&gt;Lakeflow Spark Declarative Pipelines&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.databricks.com/aws/en/ldp/concepts/flows" rel="noopener noreferrer"&gt;Flows&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.databricks.com/aws/en/ldp/concepts/materialized-views" rel="noopener noreferrer"&gt;Materialized views&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.databricks.com/aws/en/ldp/incremental-refresh" rel="noopener noreferrer"&gt;Incremental refresh for materialized views&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.databricks.com/aws/en/ldp/developer/ldp-sql-ref-create-materialized-view" rel="noopener noreferrer"&gt;CREATE MATERIALIZED VIEW&lt;/a&gt; e a cláusula &lt;a href="https://docs.databricks.com/aws/en/ldp/developer/ldp-sql-ref-create-materialized-view-refresh-policy" rel="noopener noreferrer"&gt;REFRESH POLICY&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://community.databricks.com/t5/data-engineering/limited-concurrent-running-dlt-s-within-a-pipeline/td-p/106789" rel="noopener noreferrer"&gt;Limite de 16 tabelas processadas ao mesmo tempo numa pipeline&lt;/a&gt;, discussão na comunidade Databricks
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.databricks.com/aws/en/dev-tools/bundles/resources" rel="noopener noreferrer"&gt;Declarative Automation Bundles resources&lt;/a&gt;, onde fica o YAML da pipeline
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.databricks.com/aws/en/data-governance/unity-catalog/" rel="noopener noreferrer"&gt;Unity Catalog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dataengineering</category>
    </item>
  </channel>
</rss>
