Apache Airflow em 2026: orquestração de pipelines, DAG e perguntas de entrevista
Dominar o Apache Airflow 3.2 com este tutorial prático: escrita de DAG com o Task SDK, padrões de orquestração de pipelines, partições de assets e perguntas reais de entrevista para vagas de data engineering em 2026.

O Apache Airflow 3.2 representa a evolução mais significativa da plataforma de orquestração open source desde a reformulação arquitetural da versão 3.0. Com mais de 10 milhões de downloads mensais no PyPI e adoção em empresas que vão da Airbnb ao Spotify, o Airflow continua sendo a ferramenta dominante para construir, agendar e monitorar pipelines de dados. Este tutorial cobre a escrita de DAG com o novo Task SDK, os padrões de orquestração de pipelines e as perguntas de entrevista que aparecem em vagas de data engineering.
O Airflow 3.2, lançado em abril de 2026, introduz as partições de assets para um agendamento data-aware granular, o suporte assíncrono nativo no PythonOperator e os deployments multiequipe. Todas as importações de DAG passam agora pelo namespace estável airflow.sdk introduzido no Airflow 3.0.
Escrita de DAG com o Task SDK do Airflow
O Airflow 3.0 introduziu o Task SDK, um pacote independente que desacopla as definições de DAG dos componentes internos do Airflow. O objetivo: escrever DAGs portáteis e estáveis entre versões, capazes de sobreviver às atualizações do Airflow sem alterações de código. Todos os objetos centrais — DAG, dag, task, BaseOperator, Connection, Variable — residem agora sob airflow.sdk.
Os caminhos de importação legados (airflow.decorators.task, airflow.models.dag.DAG) ainda funcionam na 3.2, mas estão marcados como obsoletos e serão removidos em uma versão futura.
# etl_daily_revenue.py
import pendulum
from airflow.sdk import dag, task
@dag(
schedule="@daily",
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
tags=["finance", "etl"],
)
def etl_daily_revenue():
@task()
def extract_transactions() -> list[dict]:
# Pulls raw transactions from the payments API
import requests
response = requests.get("https://api.internal/payments/daily")
return response.json()["transactions"]
@task(multiple_outputs=True)
def transform(transactions: list[dict]) -> dict:
# Aggregates by currency and computes totals
totals = {}
for tx in transactions:
currency = tx["currency"]
totals[currency] = totals.get(currency, 0) + tx["amount"]
return {"totals": totals, "count": len(transactions)}
@task()
def load(totals: dict, count: int):
# Inserts aggregated row into the warehouse
from warehouse import insert_revenue_summary
insert_revenue_summary(totals=totals, transaction_count=count)
raw = extract_transactions()
result = transform(raw)
load(result["totals"], result["count"])
etl_daily_revenue()O decorador @dag substitui o gerenciador de contexto tradicional with DAG(...). O decorador @task transforma funções Python simples em tarefas do Airflow, com a serialização XCom tratada automaticamente. Chamar transform(raw) declara uma dependência — o Airflow constrói as arestas do DAG a partir do grafo de chamadas de funções.
Mapeamento dinâmico de tarefas para cargas variáveis
DAGs estáticos falham quando o número de itens a processar muda entre execuções. O mapeamento dinâmico de tarefas, estável desde o Airflow 2.4 e refinado no ramo 3.x, resolve isso gerando as tarefas em tempo de execução via .expand().
# etl_multi_region.py
import pendulum
from airflow.sdk import dag, task
@dag(
schedule="@hourly",
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
tags=["regional", "etl"],
)
def etl_multi_region():
@task()
def get_regions() -> list[str]:
# Returns the active regions from config
return ["us-east-1", "eu-west-1", "ap-southeast-1"]
@task()
def process_region(region: str) -> dict:
# Processes events for a single region
from data_processor import aggregate_events
return aggregate_events(region)
@task()
def merge_results(results: list[dict]):
# Combines all regional outputs into a single report
from reporter import publish_global_report
publish_global_report(results)
regions = get_regions()
# .expand() creates one mapped task instance per region
processed = process_region.expand(region=regions)
merge_results(processed)
etl_multi_region()Em tempo de execução, o Airflow cria três instâncias paralelas de process_region — uma por região. Se uma quarta região aparecer amanhã, nenhuma alteração no código do DAG é necessária. A tarefa merge_results aguarda a conclusão de todas as instâncias mapeadas antes de executar.
Por padrão, o Airflow limita as tarefas mapeadas a 1024 instâncias por mapeamento. Esse limite é alterado com max_map_length na configuração do DAG ao processar conjuntos de dados maiores.
Partições de assets: agendamento data-aware no Airflow 3.2
Antes do Airflow 3.2, o agendamento data-aware operava no nível do asset: quando um DAG produtor atualizava um asset, todos os DAGs consumidores eram disparados independentemente de qual fatia de dados havia mudado. As partições de assets corrigem isso ao habilitar uma granularidade no nível da partição.
Considere um cenário em que três DAGs upstream produzem estatísticas horárias de jogadores para diferentes ligas esportivas. Um DAG analítico downstream só deveria disparar quando as três ligas tiverem publicado dados para a mesma hora.
# downstream_analytics.py
import pendulum
from airflow.sdk import dag, task
from airflow.timetables.assets import CronPartitionTimetable
# Define partitioned assets with hourly granularity
nba_stats = Asset("s3://datalake/nba/hourly/", partitions=CronPartitionTimetable("0 * * * *"))
epl_stats = Asset("s3://datalake/epl/hourly/", partitions=CronPartitionTimetable("0 * * * *"))
nfl_stats = Asset("s3://datalake/nfl/hourly/", partitions=CronPartitionTimetable("0 * * * *"))
@dag(
# Triggers only when all three assets have matching partition
schedule=(nba_stats & epl_stats & nfl_stats),
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
)
def unified_sports_analytics():
@task()
def aggregate_all_leagues(**context):
partition = context["partition"]
# Process only the specific hourly slice across all leagues
from analytics import build_cross_league_report
build_cross_league_report(partition=partition)
aggregate_all_leagues()
unified_sports_analytics()O agendamento particionado elimina as execuções de pipeline redundantes. O DAG downstream só dispara quando a partição exata de que precisa está disponível em todas as fontes upstream — nem antes, nem sobre dados parciais.
Pronto para mandar bem nas entrevistas de Data Engineering?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Tarefas assíncronas nativas para cargas intensivas em E/S
O Airflow 3.2 adiciona suporte assíncrono nativo no PythonOperator. Antes, executar operações de E/S concorrentes (milhares de chamadas de API, downloads de arquivos em lote) exigia escrever operadores deferrable personalizados. Agora, basta passar diretamente uma função async.
# async_file_download.py
import asyncio
import aiohttp
from airflow.sdk import dag, task
import pendulum
@dag(
schedule="@daily",
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
tags=["async", "download"],
)
def async_file_download():
@task()
async def download_files():
urls = [f"https://data.source/files/{i}.csv" for i in range(500)]
async with aiohttp.ClientSession() as session:
# Downloads 500 files concurrently instead of sequentially
tasks = [fetch_and_save(session, url) for url in urls]
results = await asyncio.gather(*tasks)
return {"downloaded": len(results)}
download_files()
async def fetch_and_save(session: aiohttp.ClientSession, url: str):
async with session.get(url) as resp:
content = await resp.read()
filename = url.split("/")[-1]
with open(f"/data/downloads/{filename}", "wb") as f:
f.write(content)
return filename
async_file_download()A abordagem assíncrona baixa 500 arquivos em paralelo por meio de um único slot de worker, contra 500 chamadas HTTP sequenciais na versão síncrona. Para cargas limitadas por E/S, isso se traduz em ganhos de velocidade de uma ordem de magnitude sem provisionar workers adicionais.
Arquitetura do Airflow: componentes e fluxo de execução
Compreender a arquitetura do Airflow é essencial tanto para operá-lo em produção quanto para responder a perguntas de entrevista. Cinco componentes interagem durante cada execução de DAG:
- Scheduler — Faz o parse dos arquivos de DAG, resolve as dependências e enfileira as tarefas para execução. No Airflow 3.x, o scheduler opera sem estado contra o banco de metadados.
- Executor — Determina onde as tarefas são executadas. O
LocalExecutorgerencia instalações em uma única máquina. OCeleryExecutordistribui entre nós workers. OKubernetesExecutorsobe um pod por tarefa. - Workers — Executam o código real das tarefas. Com a nova Task Execution API do Airflow 3.0, os workers se comunicam por meio de um contrato estável, o que permite a execução em contêineres, ambientes edge ou runtimes externos.
- Banco de metadados — PostgreSQL (recomendado) ou MySQL. Armazena as definições de DAG, os estados das tarefas, os valores XCom, as credenciais de conexão e os logs de auditoria.
- Servidor web — A interface do Airflow para monitorar as execuções de DAG, inspecionar logs, disparar execuções manuais e gerenciar conexões.
Convém evitar o SequentialExecutor em produção: ele executa uma única tarefa por vez e existe apenas para desenvolvimento. Para ambientes nativos de Kubernetes, o KubernetesExecutor oferece o isolamento mais forte, já que cada tarefa recebe seu próprio pod com recursos e dependências independentes.
Airflow vs. Prefect vs. Dagster em 2026
O Airflow compete com duas alternativas significativas. A escolha certa depende do tamanho da equipe, da infraestrutura existente e dos tipos de pipelines que estão sendo construídos.
| Recurso | Airflow 3.2 | Prefect 3.x | Dagster 1.9 |
|---|---|---|---|
| Definição de DAG | Decoradores Python (airflow.sdk) | Decoradores Python (@flow, @task) | Decoradores Python (@asset, @op) |
| Agendamento | Cron, asset-aware, partition-aware | Cron, orientado a eventos | Cron, baseado em sensors, asset-aware |
| Modelo de execução | Scheduler centralizado + workers distribuídos | Híbrido (servidor + work pools) | dagster-daemon centralizado |
| Tarefas dinâmicas | Tarefas mapeadas via .expand() | Loops Python nativos | Partições dinâmicas |
| Suporte assíncrono | Nativo na 3.2 | Nativo desde a 2.0 | Operações de E/S assíncronas |
| Isolamento multiequipe | Integrado (experimental na 3.2) | Baseado em workspaces (Cloud) | Branch deployments |
| Tamanho da comunidade | O maior (35k+ estrelas no GitHub) | Em crescimento (18k+ estrelas) | Em crescimento (12k+ estrelas) |
| Melhor caso de uso | Pipelines complexos, multiequipe, com infraestrutura estabelecida | Equipes menores que buscam iteração rápida | Organizações centradas em assets de dados |
A vantagem do Airflow está em seu ecossistema: mais de 80 pacotes de providers que cobrem cada serviço de nuvem, banco de dados e API principais. O Prefect se destaca na experiência do desenvolvedor com menos código repetitivo. O modelo asset-centric do Dagster combina com equipes que pensam em termos de produtos de dados em vez de sequências de tarefas.
Perguntas de entrevista: Apache Airflow para data engineers
As perguntas a seguir refletem o que os gestores de contratação e os engenheiros sêniores perguntam durante as entrevistas de data engineering em empresas que rodam o Airflow em produção.
O que é um DAG e como o Airflow o utiliza?
Um DAG (Directed Acyclic Graph) define um workflow como uma coleção de tarefas com dependências, garantido sem referências circulares. O Airflow faz o parse dos arquivos Python da pasta dags/, constrói o grafo de dependências e o scheduler determina a ordem de execução. Cada execução de DAG cria um objeto DagRun vinculado a uma data lógica. A restrição «acíclico» garante que o scheduler sempre possa encontrar uma ordem de execução válida — a tarefa A executa antes da tarefa B, nunca o contrário ao mesmo tempo.
Como o XCom funciona e quando deve ser evitado?
O XCom (cross-communication) transmite pequenas quantidades de dados entre tarefas. Uma tarefa empurra um valor de retorno para o XCom; as tarefas downstream o recuperam. O Task SDK cuida disso automaticamente ao passar valores de retorno entre tarefas decoradas. O XCom armazena os dados no banco de metadados por padrão, o que o torna inadequado para grandes conjuntos de dados (qualquer coisa acima de alguns KB). Para transferir grandes volumes de dados, convém usar armazenamento externo (S3, GCS) e passar apenas o caminho de referência pelo XCom.
Explique a diferença entre schedule, start_date e catchup.
O parâmetro schedule (renomeado de schedule_interval no Airflow 3.x) define com que frequência o DAG é executado: uma string cron, um timedelta, um objeto timetable ou um gatilho de asset. O start_date define a data lógica mais antiga para a qual uma execução de DAG pode ser criada. catchup=True (valor padrão) cria execuções de DAG para todos os intervalos perdidos entre start_date e o momento atual. Definir catchup=False instrui o scheduler a ignorar os intervalos passados e agendar apenas a partir do tempo atual em diante. Um padrão comum em produção: catchup=False para os DAGs operacionais e catchup=True para os backfills históricos.
Em que o KubernetesExecutor difere do CeleryExecutor?
O CeleryExecutor mantém um pool de processos workers de longa duração conectados por um broker de mensagens (Redis ou RabbitMQ). As tarefas são enfileiradas e executadas nos workers disponíveis. O KubernetesExecutor cria um novo pod do Kubernetes para cada tarefa, usando a imagem Docker e os requisitos de recursos da tarefa. O Celery oferece menor latência (sem sobrecarga de inicialização de pod) e funciona bem para cargas homogêneas. O KubernetesExecutor proporciona um isolamento mais forte, controle de recursos por tarefa e elimina a necessidade de gerenciar um pool de workers estático — ideal para cargas heterogêneas em que as tarefas têm requisitos diferentes de dependências e memória.
Quais estratégias existem para lidar com falhas de tarefas?
O Airflow oferece vários mecanismos de tratamento de falhas. retries e retry_delay configuram novas tentativas automáticas com backoff exponencial. O on_failure_callback dispara lógica personalizada (alertas no Slack, incidentes no PagerDuty) quando uma tarefa falha. O trigger_rule controla como as tarefas downstream respondem — all_success (padrão), one_success, all_failed ou none_failed_min_one_success. Para problemas transitórios de infraestrutura, o parâmetro retry_exponential_backoff=True aumenta o tempo de espera entre as tentativas. Os SLAs (agora Deadline Alerts na 3.x) monitoram a duração de execução e disparam callbacks quando as tarefas excedem o tempo de execução esperado.
Boas práticas de produção para deployments do Airflow
Rodar o Airflow de forma confiável em escala exige atenção a vários padrões operacionais que vão além de escrever DAGs corretos.
Tarefas idempotentes. Cada tarefa deveria produzir o mesmo resultado quando executada várias vezes com as mesmas entradas. Convém usar INSERT ... ON CONFLICT ou MERGE em vez de um simples INSERT. Particionar os dados de saída por data lógica. Isso garante novas tentativas e backfills seguros, sem duplicação de dados.
DAGs pequenos e focados. Convém resistir à tentação de construir DAGs monolíticos com dezenas de tarefas. Dividir os pipelines complexos em vários DAGs conectados por assets (antes datasets). DAGs menores fazem parse mais rápido, são mais fáceis de depurar e permitem reinícios parciais do pipeline.
Gerenciamento de conexões. Armazenar todas as credenciais no gerenciador de conexões do Airflow ou em um backend de secrets externo (AWS Secrets Manager, HashiCorp Vault). Nunca codificar credenciais nos arquivos de DAG. O Airflow 3.x criptografa os campos de conexão em repouso no banco de metadados.
Monitoramento e alertas. Exportar as métricas do Airflow para o Prometheus ou StatsD. Acompanhar scheduler_heartbeat, dag_processing.total_parse_time e executor.queued_tasks. O Airflow 3.2 adiciona traces do OpenTelemetry para uma observabilidade de pipeline de ponta a ponta.
Preparando uma entrevista de data engineering que cobre a orquestração de pipelines? A SharpSkill oferece perguntas de entrevista do Airflow dedicadas e módulos de prática que reproduzem cenários reais de ambientes de produção.
Comece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Conclusão
- O Airflow 3.2 introduz o Task SDK (
airflow.sdk) como API estável para a escrita de DAG — convém migrar as importações agora para evitar rupturas em versões futuras - As partições de assets habilitam um agendamento data-aware no nível da partição, eliminando os disparos de pipeline redundantes em atualizações de dados parciais
- O suporte assíncrono nativo no PythonOperator lida com cargas intensivas em E/S (downloads em lote, fan-outs de API) sem operadores deferrable personalizados
- O mapeamento dinâmico de tarefas via
.expand()se adapta ao tamanho variável das cargas em tempo de execução, sem alterações no código do DAG - A preparação para entrevistas deve cobrir o funcionamento dos DAGs, os trade-offs entre executors (Celery vs. Kubernetes), as limitações do XCom e os padrões de idempotência
- Os deployments de produção se beneficiam de DAGs pequenos e idempotentes, de um gerenciamento de secrets externo e da exportação de métricas para plataformas de observabilidade
Comece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Tags
Compartilhar
Artigos relacionados

Apache Spark com Python: construindo pipelines de dados passo a passo
Tutorial prático de PySpark cobrindo operações com DataFrame, construção de pipelines ETL e recursos do Spark 4.0. Inclui exemplos de código prontos para produção voltados a engenheiros de dados que se preparam para entrevistas técnicas.

ETL vs ELT em 2026: Arquitetura de Pipelines de Dados Explicada
Comparação completa entre arquiteturas ETL e ELT para pipelines de dados em 2026, incluindo análise de custos, performance, exemplos de código e critérios de decisão para engenheiros de dados.

Top 25 Perguntas de Entrevista para Engenharia de Dados em 2026
Guia completo com as 25 perguntas mais relevantes para entrevistas de engenharia de dados em 2026. Inclui SQL, Spark, Kafka, ETL/ELT, modelagem de dados e design de pipelines.