ETL de farmácias: do coletor Java até o Redshift e Power BI

TL;DR - Pipeline farmácias → S3 Parquet → Python/Iceberg → Redshift; app Flutter, API Java e Power BI. Os desafios reais: volume, consistência entre camadas e operação (monitorar e reprocessar).


Desenhei e rodei um pipeline de dados que começa nas farmácias, passa por um datalake em S3 com Apache Iceberg e desemboca no Redshift. O coletor em Java chegou a mais de 5.000 lojas (meta era 16.000) ao longo de cerca de um ano. O fluxo geral está no diagrama abaixo.

flowchart TB
  Farmacia[Farmácias] --> Coletor[Coletor Java]
  Coletor --> Gateway[Gateway Java]
  Gateway --> S3[S3 Parquet/bronze]
  S3 --> Python[Pipeline Python]
  Python --> Iceberg[Iceberg silver/gold]
  Iceberg --> Redshift[Redshift]
  Redshift --> App[App Flutter iOS/Android]
  Redshift --> API[API Java]
  Redshift --> PBI[Power BI]

Da loja ao S3 (bronze)

Nas lojas roda um coletor em Java que envia só as tabelas que interessam: vendas, estoque e afins. O destino é um gateway, também em Java, que valida o básico e grava em Parquet no S3, particionado por data e origem.

Na prática isso gerava cerca de 100 mil arquivos Parquet por ciclo (até mil linhas por arquivo) e algo em torno de 6 GB/hora entrando e sendo processados. Particionamento por data e por origem foi essencial para não matar o pipeline nas leituras e para reprocessar só o que fosse necessário.

Bronze → Iceberg → Redshift (silver e gold)

Uma pipeline em Python lê esses Parquet, normaliza e sobe para o Iceberg. Separei em silver (dados limpos e conformes) e gold (agregados e visões prontas para consumo). Do Iceberg copio para o Redshift para consultas analíticas.

Quem consome no fim: app em Flutter (iOS e Android) com dados quase em tempo real (estoque, vendas, performance dos vendedores, margem, comparação entre regiões), API Java para parceiros e Power BI para relatórios dos analistas.

Onde doeu (e o que ajudou)

Volume. Muitas farmácias, muitos eventos. Particionamento certo no S3 e no Iceberg reduziu custo de leitura e permitiu reprocessar por partição sem reescanear tudo.

Consistência entre camadas. Manter bronze, silver e gold alinhados sem travar o pipeline exige regras claras de schema, nomenclatura e (quando possível) contratos. Quando algo quebra, o problema costuma aparecer na camada de consumo; ter partições bem definidas ajuda a isolar e corrigir.

Governança. Quem pode ver o quê no Redshift e no Power BI, e como documentar as fontes, virou dor constante. Definir ownership por conjunto de tabelas e manter um glossário mínimo (origem, refresh, uso esperado) poupa tempo depois.

Operação. O gargalo que mais pesou foi monitorar falhas no coletor ou no gateway e reprocessar quando preciso. Investir em alertas por partição/janela e em jobs idempotentes de reprocessamento paga rápido.

Em resumo

  • Bronze no S3 em Parquet: particionar por data e origem; arquivos pequenos (até ~mil linhas) facilitam reprocesso granular.
  • Silver/gold no Iceberg: separar “dado limpo” de “agregado pronto para consumo” deixa o Redshift e o Power BI mais simples e previsíveis.
  • Redshift como camada de consumo: app, API e BI leem da mesma fonte; o trabalho pesado fica no datalake.
  • Governança e operação: definir quem é dono do quê e como reprocessar (e monitorar) evita surpresas quando o volume cresce.

Se você for montar algo parecido, reserve tempo desde o início para particionamento, reprocessamento idempotente e governança básica. O resto escala melhor quando isso está resolvido.