Seja bem-vindo ao Ingestão no Limite, o desafio de Engenharia de Dados focado em eficiência extrema, código performático e FinOps.
Contexto Narrativo:
Uma agência de marketing B2B precisa de uma base de dados grande e robusta para criar campanhas automatizadas e conquistar o maior número possível de prospectos. No entanto, a agência não está disponível a investir em máquinas virtuais, clusters Kubernetes ou instâncias no Databricks, pois acredita que não são necessários custos elevados para atingir seus objetivos.
Eles baixaram arquivos de empresas no formato CSV pelo site dados.gov.br. Contudo, não conseguem sequer abrir esses arquivos, pois estão compactados em .zip, possuem um formato interno incomum e, além disso, são grandes demais para manipular no Excel.
Diante disso, a agência contratou você para criar um processo de ingestão e tratamento simples desses dados, de forma a permitir melhores consultas utilizando ferramentas de BI, como Tableau, Metabase ou Power BI.
O detalhe importante: o único equipamento disponível é um notebook antigo, que eles acreditam ser suficiente para o serviço.
Criar o pipeline de ingestão e tratamento dos dados empresariais mais eficiente possível, operando sob rigorosas restrições de hardware (máximo de 1 GB de RAM, 2 CPUs e 60 min para processar ~68,6M linhas).
Ao final, seu trabalho deve gerar uma tabela padronizada e pronta para BI no PostgreSQL. Você decide a arquitetura: pode usar object storage compatível com S3 como apoio (staging, Parquet, Delta Lake, Iceberg) ou ir direto ao Postgres — o que importa é passar nos gates e vencer no ranking.
Ao longo do processo, você deverá manipular múltiplos arquivos .zip, converter encodings e tipos de dados, aplicar regras rigorosas de qualidade de dados e carregar todas as linhas da origem (sem filtro), derivando colunas de negócio que segmentam a base para o BI — por exemplo, faixa de capital_social, flag is_mei, grupo de natureza jurídica e presença de ente federativo. É uma abordagem ELT: carregue o dado bruto e classifique-o em colunas, em vez de descartar registros.
Todos os critérios serão verificados automaticamente. Apenas soluções que passem em todos os gates serão consideradas para o ranking.
Esse desafio testa sua habilidade em otimizar, manipular grandes volumes de dados e desenvolver soluções robustas, criativas e enxutas — uma simulação de cenário real, onde a infraestrutura é fornecida e você escolhe a melhor abordagem.
A competição disponibiliza duas ferramentas. Você escolhe como usá-las:
| Serviço | Papel | Obrigatório? |
|---|---|---|
PostgreSQL (db_empresas) |
Destino final da tabela de negócio para BI | Sim — tabela {participante}_empresas |
| S3-compatível (MinIO no laboratório) | Object storage para staging, intermediários ou lake | Não — uso opcional a seu critério |
db_empresas.public.{participante}_empresas
Onde {participante} é exatamente o valor do campo participante no seu JSON de submissão (ex.: renan_python → renan_python_empresas).
- Faça o Fork deste repositório.
- Desenvolva seu código de ingestão em um repositório público seu (
Dockerfilena raiz +src/). No fork oficial, envie apenassubmissions/seu_usuario.json. - Abra um Pull Request contra a branch
maincom seu arquivo emsubmissions/seu_usuario.jsone faça merge após revisão. - Após o merge, o servidor local (Hardware Celeron) enfileira a avaliação, executa preflight, roda o pipeline no Docker isolado e coleta métricas.
- Se passar em todos os gates, seu score composto (tempo + RAM + storage) entra no Ranking Oficial.
A avaliação não roda enquanto o PR está aberto — só depois que o JSON entra na
main. O organizador pode reavaliar manualmente via Actions → Run workflow (sem novo PR).
Para não travar no contrato de dados ou ser desclassificado por estouro de memória, leia os guias abaixo antes de codar:
- 📄 Regras de Negócio e Contrato de Dados — Schema (13 colunas), carga completa, tipos de dados e encoding.
- 🏛️ Arquitetura do Projeto e Workflow — Componentes, fluxos, gates e diagramas.
- 💻 Stack do Servidor, Variáveis e Acesso na Avaliação — Como a avaliação conecta ao Postgres/S3, env vars, licença do MinIO e limites de hardware.
- 🚦 Gates, Ranking e Juiz Automático — Gates de aprovação, métricas, timeout, fila e SQL de validação.
- 🐍 Judge (
/evaluator/judge) —validar.py+ SQL executado pelo evaluator. - 📑 Checklist Obrigatório para Pull Request — Requisitos antes de abrir o PR e fazer merge para avaliação.
Entre soluções classificadas (todos os gates aprovados), a ordem é dada por um score composto (menor vence) — não é mais só velocidade:
score = 0.60·(tempo/3600) + 0.25·(peak_ram/1024) + 0.15·(storage_total/4096)
- 60% tempo, 25% RAM, 15% storage — recompensa eficiência holística.
- Ser mais rápido não basta se você desperdiça RAM (o recurso escasso: 1 GB) ou escreve uma tabela inchada.
- Desempates (se o score empatar): tempo → storage → RAM → ordem de chegada.
"Engenharia de dados de verdade não é sobre contratar o maior cluster da nuvem, é sobre escrever código otimizado."
Detalhes completos e exemplos em Gates, Ranking e Juiz Automático.
Dois repositórios, papéis diferentes
Repositório O que vai lá Seu repo público de solução Dockerfile,src/,participante.json,requirements.txt— só o pipelineFork deste repo oficial Apenas submissions/seu_usuario.jsonapontando para o seu repoNão abra PR com o código da ingestão dentro do repo oficial (
docs/,evaluator/, etc.). O evaluator clona o URL do camporepositoriodo JSON — ele precisa ser o seu repositório, enxuto e com oDockerfilena raiz.
- Crie um novo repositório público na sua conta do GitHub (ex.:
seu_usuario/ingestao-empresas). - Use este repo oficial só como referência (documentação em
/docse starter emsubmitter/). Copie o conteúdo desubmitter/para a raiz do seu repo. - Estrutura mínima recomendada no seu repositório (após copiar de
submitter/):
seu-repo-da-solucao/
├── Dockerfile # obrigatório — na raiz; dispara a ingestão ao iniciar o container
├── requirements.txt # dependências do build (se usar Python, etc.)
├── participante.json # seu identificador + URL deste mesmo repo (copie de participante.json.example)
└── src/
└── main.py # entrypoint do pipeline (ou outro layout, ajustando o Dockerfile)
- Renomeie
participante.json.example→participante.json(copiado desubmitter/) e preencha com seu usuário e a URL do seu repo. - Desenvolva na linguagem que desejar (Python, Rust, Go, C++, etc.) — o starter usa Python apenas como ponto de partida.
- Grave a tabela final em
db_empresas.public.{participante}_empresasconforme o contrato de dados. - Object storage S3 é opcional; se usar, limite-se ao prefixo
s3://marketing-leads/{participante}/. Projete o código contra a API S3 genérica — o MinIO na avaliação é apenas alvo de laboratório (ver licença e alternativas).
O participante.json na raiz do seu repo é para organização e deve bater com o JSON que você enviará no fork (mesmos participante e repositorio). O evaluator não lê esse arquivo do seu repo — ele usa apenas o JSON em submissions/ no fork.
- Faça um Fork deste repositório (
mpraes/ingestao_no_limite). - No fork, crie somente
submissions/seu_usuario.json(não movaDockerfilenemsrc/para cá). - Use a mesma estrutura do
participante.jsondo seu repo de solução:
{
"participante": "seu_usuario",
"repositorio": "https://github.com/seu_usuario/seu-repo-da-solucao",
"email": "seu_email@exemplo.com"
}O campo email é opcional, mas recomendado: após a avaliação o workflow envia um relatório com status, tempo, storage, pico de RAM e posição no ranking.
- Abra um Pull Request contra a
maindo repo oficial e faça merge. Após o merge, o workflow clona orepositorioacima e roda oDockerfilede lá.
ingestao_no_limite/
├── README.md
├── docs/ # documentação pública
├── submissions/ # metadados de submissão (único conteúdo do PR no fork)
├── submitter/ # starter — copie para a raiz do SEU repo de solução
│ ├── Dockerfile
│ ├── requirements.txt
│ ├── participante.json.example
│ └── src/
└── evaluator/ # tooling do servidor (organizadores)
├── evaluator.sh
├── judge/
├── scripts/
└── logs/
Para manter a competição divertida e o servidor saudável:
| Regra | Valor |
|---|---|
| RAM máxima do container | 1 GB (sem swap) |
| CPUs máximas | 2 |
| Timeout do pipeline | 60 min (hard cap; ~68,6M linhas, 7+6 colunas → ~19k linhas/s) |
| Build da imagem | 15 minutos (separado; não conta no ranking) |
| Avaliações simultâneas | 1 (fila única — nunca em paralelo) |
| Intervalo entre avaliações | 15 minutos de cooldown (fairness) |
| PRs duplicados | apenas o commit mais recente é avaliado |
Soluções que excederem o timeout ou forem mortas por OOM recebem status de erro e não entram no ranking.
Na avaliação e no desenvolvimento local, o desafio pode disponibilizar MinIO dockerizado apenas como alvo S3 local para testes e benchmark — não como recomendação de produção.
- O servidor MinIO é licenciado sob GNU AGPLv3; os binários recentes também estão sujeitos à MinIO Software License, que restringe o uso sem contrato enterprise a uma instância, em ambiente não produtivo, para avaliação interna.
- Usar MinIO sem modificações como componente interno de pipeline/CI não obriga que o seu código de ingestão seja AGPLv3 — o copyleft atinge trabalhos derivados do MinIO, não programas independentes que apenas falam S3.
- Para produção ou replicação do desafio por outros grupos, cada time deve escolher sua própria solução S3-compatível (AWS S3, Ceph RADOS Gateway, SeaweedFS, etc.) e avaliar juridicamente o uso pretendido.
Detalhes, alternativas sugeridas e orientações para organizadores estão em Stack do Servidor — object storage S3-compatível.
Acesse esse site para ver o ranking se quiser - https://lnk.ink/5R2NA
É um encurtador de link pois eu fiz o site via free ngrok então pode ter um aviso disso.