Olá a todos.
Se há coisa que curto é automatizar trabalhos repetitivos, mas quando preciso de orquestrar workflows e a única resposta que ouço é “usa Airflow” fico mesmo atrofiado. Não me interpretem mal — o Apache Airflow tem o seu lugar, e durante anos foi praticamente a única opção séria para quem precisava de orquestração de pipelines de dados. Mas sejamos honestos: montar um Airflow, gerir as dependências Python, lidar com os DAGs, manter aquela infraestrutura toda a funcionar… é um trabalho a tempo inteiro. E nós já temos trabalho suficiente a tempo inteiro.
Com isso em mente, hoje venho falar-vos de uma ferramenta que tenho andado a explorar (sim… tinkering) e que, na minha opinião, merece muito mais atenção do que aquela que tem recebido: o Kestra. Uma plataforma open-source de orquestração declarativa e event-driven que, para muitos dos nossos casos de uso — especialmente em ambientes on-prem e homelab — pode ser exactamente o que andávamos à procura.
O problema que o Kestra resolve
Quem já trabalhou com orquestração de workflows sabe que o mercado se divide basicamente em dois mundos. De um lado, temos os frameworks code-centric como o Airflow, o Prefect, o Dagster — ferramentas poderosas, sem dúvida, mas que exigem que sejas developer Python. Do outro lado, temos as plataformas drag-and-drop tipo Zapier ou n8n, que são fantásticas para automações simples mas que rebentam pelas costuras quando precisas de algo minimamente customizado.
O Kestra posiciona-se no meio disto tudo. E fá-lo de uma forma que, confesso, me surpreendeu pela positiva.
A filosofia é simples: defines os teus workflows em YAML — sim, YAML, aquele formato que já usamos para tudo em DevOps — e o Kestra trata do resto. Scheduling, event triggers, retries, error handling, paralelismo, subflows… tudo declarativo, tudo versionável, tudo auditável. E o melhor? Não estás preso ao Python. Podes correr scripts em Python, R, Julia, Node.js, Go, Rust, Shell, SQL, ou literalmente qualquer coisa que corra num container.
Isto, para quem gere equipas heterogéneas ou para quem tem um homelab onde corre de tudo um pouco, é ouro.
Porquê o Kestra e não o Airflow?
O Airflow é o incumbente. Tem o maior ecossistema, a maior comunidade, e a maior base instalada. Mas tem problemas sérios que qualquer pessoa que o tenha usado em produção conhece:
O deployment é pesado. Precisas de configurar um metadata database, um message broker, gerir dependências Python que entram em conflito umas com as outras, e rezar para que o scheduler não decida fazer birra às 3 da manhã. A definição de workflows é Python-only. Isto significa que o teu colega de equipa que é wizard em SQL ou em Bash, mas que não domina Python, fica de fora. E por fim, não é event-driven de raiz. Podes martelar event triggers no Airflow? Podes. Mas é como colocar pneus de neve num carro de Fórmula 1 — funciona, mas não foi desenhado para isso.
O Kestra, por outro lado, foi construído de raiz para ser event-driven, ou como um amigo meu diz, if/then automation. Os triggers — sejam eles baseados em schedule, webhooks, eventos de ficheiros, mensagens Kafka, ou qualquer outro evento — são cidadãos de primeira classe na plataforma. Defines tudo no mesmo YAML do workflow e pronto. Sem configurações extra, sem serviços adicionais, sem dores de cabeça.
Instalação: Docker compose e pronto
Como já sabem, ando sempre à procura de soluções que sejam fáceis de fazer self-host. E aqui o Kestra brilha. Com dois comandos tens a coisa a correr:
curl -o docker-compose.yml \
https://raw.githubusercontent.com/kestra-io/kestra/develop/docker-compose.yml
docker compose up -d
Sim, contaram bem. Dois comandos. Abre o browser em http://localhost:8080 (ou ip do vosso host) e tens o Kestra a correr com a UI completa, editor de código integrado, e tudo o que precisas para começar a criar workflows. Comparado com o processo de instalação do Airflow, isto é quase poesia.
Para quem quer algo mais robusto — e quem me conhece sabe que “se é crítico, tem redundância” — podemos personalizar o docker-compose para incluir PostgreSQL como backend de persistência, configurar workers adicionais, e adicionar monitorização:
services:
kestra:
image: kestra/kestra:latest
container_name: kestra
ports:
- "8080:8080"
- "8081:8081"
environment:
KESTRA_CONFIGURATION: |
datasources:
postgres:
url: jdbc:postgresql://postgres:5432/kestra
driverClassName: org.postgresql.Driver
username: kestra
password: ${KESTRA_DB_PASSWORD}
kestra:
server:
basicAuth:
enabled: true
username: admin
password: ${KESTRA_ADMIN_PASSWORD}
repository:
type: postgres
storage:
type: local
local:
basePath: /app/storage
queue:
type: postgres
volumes:
- kestra-data:/app/storage
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
networks:
- kestra-network
postgres:
image: postgres:16-alpine
container_name: kestra-postgres
environment:
POSTGRES_DB: kestra
POSTGRES_USER: kestra
POSTGRES_PASSWORD: ${KESTRA_DB_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U kestra"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- kestra-network
volumes:
kestra-data:
postgres-data:
networks:
kestra-network:
driver: bridge
Criem um ficheiro .env na mesma pasta com as vossas passwords:
KESTRA_DB_PASSWORD=a_vossa_password_segura
KESTRA_ADMIN_PASSWORD=outra_password_segura
E executem docker compose up -d. Simples, limpo, funcional.
O Primeiro Flow: Mãos à Obra
A unidade fundamental no Kestra chama-se Flow. Um flow é um ficheiro YAML que define um workflow completo — tasks, triggers, inputs, outputs, error handling — tudo num único sítio. Vamos criar um exemplo prático que faz sentido no mundo real: um flow que monitoriza um directório por novos ficheiros CSV, processa-os, e envia uma notificação.
id: csv-processor
namespace: production.data
description: |
Processa ficheiros CSV depositados no storage
e envia notificação via webhook.
inputs:
- id: notification_url
type: STRING
defaults: "https://hooks.slack.com/services/XXX/YYY/ZZZ"
tasks:
- id: list_files
type: io.kestra.plugin.core.flow.Log
message: "A verificar novos ficheiros CSV..."
- id: process_csv
type: io.kestra.plugin.scripts.python.Script
containerImage: python:3.11-slim
beforeCommands:
- pip install pandas
script: |
import pandas as pd
import json
# Exemplo de processamento
df = pd.read_csv("{{ trigger.uri }}")
# Limpeza e transformação
df.dropna(inplace=True)
df.columns = [col.strip().lower().replace(' ', '_') for col in df.columns]
# Estatísticas básicas
stats = {
"total_rows": len(df),
"columns": list(df.columns),
"null_counts": df.isnull().sum().to_dict()
}
# Output para o próximo task
print(json.dumps(stats))
- id: notify
type: io.kestra.plugin.core.http.Request
uri: "{{ inputs.notification_url }}"
method: POST
contentType: application/json
body: |
{
"text": "CSV processado com sucesso! Ficheiro: {{ trigger.uri }}"
}
triggers:
- id: watch_csv
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/5 * * * *"
errors:
- id: on_failure
type: io.kestra.plugin.core.flow.Log
message: "ERRO no processamento: {{ error.message }}"
Reparem na elegância disto. Num único ficheiro YAML temos a definição completa do workflow: os tasks executam-se sequencialmente, temos um trigger baseado em schedule (a cada 5 minutos), error handling, e notificação. Tudo declarativo, tudo legível, tudo versionável com Git.
Event-driven: Onde o kestra realmente brilha
Agora vamos ao que interessa. O Kestra não é apenas um scheduler glorificado — é uma plataforma event-driven de raiz. Isto significa que podemos reagir a eventos em tempo real, não apenas executar coisas em intervalos fixos.
Vejam este exemplo de um flow que reage a mensagens numa queue Kafka:
id: kafka-event-processor
namespace: production.events
tasks:
- id: log_event
type: io.kestra.plugin.core.flow.Log
message: "Evento recebido: {{ trigger.value }}"
- id: process_event
type: io.kestra.plugin.scripts.shell.Commands
containerImage: alpine:latest
commands:
- echo "A processar evento do topic {{ trigger.topic }}"
- echo "Partition: {{ trigger.partition }}"
- echo "Offset: {{ trigger.offset }}"
- id: route_event
type: io.kestra.plugin.core.flow.If
condition: "{{ trigger.value contains 'CRITICAL' }}"
then:
- id: alert_critical
type: io.kestra.plugin.core.http.Request
uri: "https://pagerduty.example.com/alert"
method: POST
contentType: application/json
body: |
{
"severity": "critical",
"message": "{{ trigger.value }}"
}
triggers:
- id: kafka_trigger
type: io.kestra.plugin.kafka.Trigger
topic: production-events
bootstrapServers: kafka:9092
groupId: kestra-consumer
serDeType: STRING
Isto é poderoso. Temos um workflow que escuta uma queue Kafka, processa eventos em tempo real, e toma decisões condicionais baseadas no conteúdo do evento. Tentem fazer isto no Airflow sem vos dar uma dor de cabeça. A capacidade de combinar scheduled workflows com event-driven triggers na mesma plataforma, com a mesma sintaxe, é um game-changer.
O ecossistema de plugins
Uma das coisas que me impressionou no Kestra é o ecossistema de plugins. E quando digo impressionou, é porque realmente há plugins para quase tudo: bases de dados (PostgreSQL, MySQL, MongoDB, Cassandra, ClickHouse), cloud providers (AWS, Azure, GCP), message brokers (Kafka, Pulsar, RabbitMQ), ferramentas de CI/CD (GitHub Actions, Terraform, Ansible), e até integrações com plataformas de AI como OpenAI, Anthropic, e modelos locais via Ollama.
Cada plugin é configurado directamente no YAML do flow. Não há pacotes Python para instalar, não há conflitos de dependências, não há containers especiais para construir. O plugin faz parte da plataforma, e tu usas-o como qualquer outro task.
Para quem tem um homelab com vários serviços a correr — e sei que muitos de vocês têm — imaginem o potencial: um único orquestrador que gere os vossos backups, monitoriza os vossos serviços, processa dados dos vossos sensores IoT, e automatiza o vosso deployment pipeline. Tudo em YAML, tudo com uma UI que até a vossa avó conseguiria navegar (quase).
A UI não é só bonita, é funcional!!
Falando em UI — e isto é algo que raramente digo sobre ferramentas de orquestração — a interface web do Kestra é genuinamente boa. Não é aquela UI básica que claramente foi uma afterthought. Tem um editor de código com syntax highlighting e auto-complete para YAML, uma vista topológica que mostra as dependências entre tasks em tempo real enquanto escreves, logs de execução detalhados, e dashboards de monitorização.
Mas o que realmente me cativou foi a capacidade de editar workflows directamente na UI e ter essas alterações reflectidas imediatamente no código YAML — e vice-versa. Isto significa que podes ter developers a trabalhar no código via Git, e stakeholders menos técnicos a ajustar parâmetros via UI, e tudo fica sincronizado. A definição YAML é sempre a source of truth, mas a UI é um primeiro cidadão de plena interacção.
Comparado com o Airflow, onde o DAG só aparece na UI depois de o fazeres deploy, e onde a UI serve basicamente para observar e não para construir, a diferença é abismal.
Infrastructure as code: git, terraform, ci/cd
Para quem — como eu — vive e respira Infrastructure as Code, o Kestra encaixa-se perfeitamente. Os flows são ficheiros YAML que vivem num repositório Git. Podes usar o plugin de Git integrado para sincronizar flows directamente com o teu repositório, ou usar o Terraform provider oficial para gerir recursos Kestra como código.
Isto é IaC puro. Os teus flows fazem parte do teu pipeline de CI/CD. Fazes push para o Git, o pipeline valida, e o Terraform aplica as mudanças no Kestra. Sem surpresas, sem configurações manuais, sem aquele medo de “quem mudou isto em produção?”.
Kestra 1.0: O que mudou recentemente?
O Kestra lançou recentemente a versão 1.0, que trouxe algumas funcionalidades que vale a pena mencionar. A principal é o suporte nativo para agentes de AI — podes orquestrar workflows que utilizam modelos da OpenAI, Anthropic Claude, Google Gemini, Mistral, e até modelos locais via Ollama, com suporte para memória, ferramentas como web search e execução de código, e até MCP clients.
Além disso, a versão 1.0 trouxe SDKs oficiais para Python, JavaScript/TypeScript, Java e Go, human-in-the-loop approvals para workflows que precisam de aprovação manual, gestão de secrets integrada, audit logs, e SLAs a nível de flow.
Para quem está a pensar em usar o Kestra para orquestrar pipelines de ML ou workflows de AI — e sejamos honestos, quem não está nesta altura? — estas funcionalidades fazem toda a diferença.
Quando NÃO usar o Kestra
Seria desonesto da minha parte não mencionar as limitações. O Kestra não é perfeito, e há cenários onde pode não ser a melhor escolha.
Se a tua equipa é 100% Python e já tem investimento significativo em Airflow ou Prefect, a migração pode não compensar. A curva de aprendizagem do YAML para orquestração é menor do que a do Python, mas se toda a gente já domina o Airflow, o custo de mudança é real.
Se precisas de dynamic DAG generation muito complexa — onde a estrutura do workflow muda dramaticamente baseada em dados de runtime — o YAML pode tornar-se verboso. É possível, mas requer mais linhas do que o equivalente em Python.
E se estás à procura de uma ferramenta com uma década de battle-testing em empresas Fortune 500, o Airflow ainda tem essa vantagem. O Kestra é mais jovem (fundado em 2021), embora esteja a crescer rapidamente — foi aliás uma das ferramentas de orquestração com maior crescimento em 2024, tendo garantido 8 milhões de dólares em financiamento.
Conclusão: Vale a pena?
Na minha opinião? Sim, sem dúvida. O Kestra preenche um espaço que estava vazio no mercado de orquestração: uma plataforma que é simultaneamente poderosa e acessível, que não te obriga a ser developer Python para orquestrar workflows, que é event-driven de raiz, e que se instala com um docker compose up.
Para quem gere homelabs, IT groups e até para equipas DevOps que querem uma alternativa mais leve ao Airflow, para empresas que precisam de orquestrar workflows entre equipas com diferentes stacks tecnológicas, o Kestra é uma opção que merece ser avaliada a sério.
O facto de ser open-source, de correr em qualquer lugar — cloud, on-prem, air-gapped — e de ter uma comunidade activa e em crescimento, são sinais muito positivos.
Como costumo dizer: experimentem, testem no vosso ambiente, e tirem as vossas próprias conclusões. Mas garanto-vos que vão ficar surpreendidos com o que conseguem fazer em meia hora com esta ferramenta.
Caso tenham dúvidas ou sugestões, sabem onde me encontrar.
Até ao próximo post!
Nuno
Links úteis:
- GitHub: https://github.com/kestra-io/kestra
- Documentação: https://kestra.io/docs
- Plugins: https://kestra.io/plugins
- Slack Community: https://kestra.io/slack
