O Custo Oculto dos Pipelines Baseados em Scripts
Olha só, todo time de dados já passou por isso: você começa com um transform_pedidos.py limpinho. Seis meses depois, tem transform_pedidos_v2.py, transform_pedidos_corrigido.py, transform_pedidos_final_USA_ESSE.py. A lógica de transformação está duplicada em uma dúzia de workflows, e qualquer mudança numa regra de negócio vira uma semana de refatoração. 😩
É exatamente esse gargalo que a composição orientada a especificação resolve. Em vez de enterrar a intenção do workflow em código imperativo, você declara o quê o pipeline deve produzir numa especificação estruturada (JSON ou YAML), e um composer monta o como a partir de capacidades reutilizáveis e versionadas.
Esse padrão brilha em ambientes regulados — saúde, finanças, ciências da vida — onde a governança exige que usuários de negócio escrevam a intenção sem tocar no código de execução, e onde trilhas de auditoria precisam ser explícitas e versionadas.
O insight central: intenção de workflow e lógica de processamento são coisas diferentes. Misturar as duas é o que te mata na escala.
Se você quer antes entender como escalar cargas Python em cluster, dá uma olhada no nosso tutorial prático de Ray na AWS.

A Arquitetura em Três Camadas
A composição orientada a especificação organiza o workflow em três camadas:
- Camada de intenção — Especificações definem o comportamento de forma declarativa.
- Camada de composição — O composer valida specs e monta pipelines.
- Camada de processamento — Processadores de capacidade executam as transformações.
A Especificação
Uma especificação é um documento JSON/YAML declarativo que descreve datasets, mapeamentos e transformações. Sem lógica de processamento — só intenção.
{
"source": ["pedidos_brutos"],
"target": ["pedidos_limpos"],
"mappings": [
{
"source_field": "data_pedido",
"target_field": "data_pedido_iso",
"capability": "formatar_data@1.2.0"
},
{
"source_field": "valor",
"target_field": "valor_brl",
"capability": "normalizar_moeda@2.0.1"
}
]
}
Repara nas versões fixadas (@1.2.0). Isso é o que garante reprodutibilidade — você nunca pega silenciosamente uma breaking change numa transformação.
O Composer
O composer é o cérebro. Ele não transforma dados. Ele:
- Valida a especificação contra um schema
- Consulta o registro de capacidades (via Amazon OpenSearch Service) para resolver ARNs e metadados
- Compila a spec em uma definição ASL (Amazon States Language)
- Inicia uma state machine do AWS Step Functions
# Lambda composer — esqueleto simplificado
import json, boto3
sfn = boto3.client("stepfunctions")
def lambda_handler(event, context):
spec = json.loads(event["spec_body"])
validar_schema(spec) # levanta exceção se inválido
states = {}
for i, mapping in enumerate(spec["mappings"]):
cap = resolver_capacidade(mapping["capability"]) # lookup no OpenSearch
states[f"step_{i}"] = {
"Type": "Task",
"Resource": cap["arn"],
"Next": f"step_{i+1}" if i + 1 < len(spec["mappings"]) else "Fim"
}
states["Fim"] = {"Type": "Succeed"}
asl = {"StartAt": "step_0", "States": states}
sfn.create_state_machine(name=spec["id"], definition=json.dumps(asl),
roleArn="arn:aws:iam::123456789012:role/sfn-exec")
return {"status": "composto", "passos": len(spec["mappings"])}
O Registro de Capacidades
Trate o registro como um artefato governado, não como uma tabela de lookup. As definições vivem em controle de versão. Seu pipeline CI/CD valida metadados e roda testes antes de publicar.
O Pipeline de Capacidades
Depois de montado, o Step Functions invoca cada Lambda de capacidade em sequência. Cada processador recebe apenas os campos que seu mapeamento referencia — uma fronteira natural de menor privilégio. Traces vão pro CloudWatch Logs.

Onde Esse Padrão Quebra (E Onde Ele Brilha)
⚠️ Limitações Que Você Precisa Encarrar
É overkill pra pipelines pequenos. Se você tem menos de três a cinco workflows, composer + registro + schema são puro overhead. Um script bem testado vence uma arquitetura distribuída sempre.
O registro vira gargalo se ficar sem governança. Sem validação em CI e version pinning, você troca scripts duplicados por um registro duplicado — mesma doença, sintoma diferente.
A complexidade do composer é real. Escrever validador de schema, resolvedor de capacidades e compilador ASL não é trivial. Orce pra isso.
🔐 Notas de Segurança
- Use SSE-KMS com chave gerenciada pelo cliente nos buckets de spec e dados.
- Force HTTPS via bucket policy (
aws:SecureTransport). - Ative node-to-node encryption no OpenSearch.
- Marque campos sensíveis na spec (
"sensitivity": "PHI") e derive a sensibilidade do target a partir do source + comportamento da capacidade.
📊 Como Medir Sucesso
Acompanhe três métricas:
| Métrica | Antes | Meta |
|---|---|---|
| LOC duplicado em transformações | Alto | Próximo de zero |
| Tempo de onboarding de dataset | Semanas | Dias |
| Novos workflows sem mudar código | 0 | Crescente |
Se esses números não mexerem, o padrão não tá se pagando.
![]()
Como Começar Essa Semana
Não reescreve tudo. Pega um pipeline existente que tenha três ou mais variantes (relatórios financeiros mensais de fontes diferentes são ideais). Depois:
- Descreve ele como uma especificação em JSON.
- Implementa 3–5 capacidades reutilizáveis como Lambdas.
- Liga uploads no S3 a uma Lambda composer.
- Mede o tempo de onboarding da próxima variante.
Se a segunda variante levar dias em vez de semanas, você validou o padrão. 🎯
Próximos Passos
- Wiring event-driven: o guia de arquiteturas event-driven da AWS Lambda mostra como conectar uploads S3 ao composer.
- Orquestração: o guia de integração Step Functions + Lambda cobre a invocação dos processadores.
- Observabilidade: publique métricas customizadas no CloudWatch pra taxa de composição e latência por passo.
Leitura Relacionada
- Alerta de Segurança em React Server Components — CVE-2025-55184 — se seus pipelines servem um frontend web, vale a pena conferir.
A vitória real não é a arquitetura. É que usuários de domínio agora escrevem workflows numa linguagem que entendem, e engenheiros param de ser compiladores humanos entre intenção de negócio e execução.
Fonte: AWS Architecture Blog — Specification-driven composition for flexible data workflows