# Boas Práticas de Desenvolvimento com AWS Glue

O AWS Glue é a solução serverless da AWS para integração, transformação (ETL) e catalogação de dados em escala. Suportando frameworks como Apache Spark, Python, Scala e Ray, o Glue evoluiu para atender desde cargas legadas até os ambientes de data lakes modernos.

Para maximizar a eficiência e o custo-benefício, é essencial adotar práticas que otimizem performance, evitem desperdícios e escolham a ferramenta certa para cada caso. Este documento detalha recomendações práticas, exemplos de uso e comparações com AWS Lambda, com foco em custo e eficiência.

```mermaid
graph TB
    A[📊 AWS Glue] --> B[🔄 ETL Jobs]
    A --> C[🗃️ Data Catalog]
    A --> D[🔍 Crawlers]
    
    B --> E[Apache Spark]
    B --> F[Python Shell]
    B --> G[Ray Framework]
    
    E --> H[G.1X Workers]
    E --> I[G.2X Workers] 
    E --> J[G.4X Workers]
    
    style A fill:#ff9900,stroke:#232f3e,stroke-width:3px,color:#fff
    style B fill:#146eb4,stroke:#232f3e,stroke-width:2px,color:#fff
    style C fill:#146eb4,stroke:#232f3e,stroke-width:2px,color:#fff
    style D fill:#146eb4,stroke:#232f3e,stroke-width:2px,color:#fff
```

## Versões do AWS Glue: 3.0, 4.0 e 5.0

A escolha da versão do Glue impacta diretamente as funcionalidades disponíveis. Abaixo está um comparativo detalhado:

```mermaid
graph LR
    subgraph "🔄 Evolução das Versões AWS Glue"
        A[📦 Glue 3.0<br/>🐍 Python 3.7<br/>⚡ Spark 3.1.1] --> B[📦 Glue 4.0<br/>🐍 Python 3.10<br/>⚡ Spark 3.3.0]
        B --> C[📦 Glue 5.0<br/>🐍 Python 3.11<br/>⚡ Spark 3.5.4]
    end
    
    A --> A1[✅ Estável para legado<br/>❌ Recursos limitados]
    B --> B1[✅ Data Lakes<br/>✅ Hudi, Iceberg, Delta<br/>❌ Sem ML/PII transforms]
    C --> C1[✅ 32% mais rápido<br/>✅ FGAC nativo<br/>✅ SageMaker integrado<br/>✅ requirements.txt]
    
    style A fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
    style B fill:#1890ff,stroke:#096dd9,stroke-width:2px,color:#fff
    style C fill:#722ed1,stroke:#531dab,stroke-width:2px,color:#fff
    style A1 fill:#f6ffed,stroke:#52c41a,stroke-width:1px
    style B1 fill:#e6f7ff,stroke:#1890ff,stroke-width:1px
    style C1 fill:#f9f0ff,stroke:#722ed1,stroke-width:1px
```

| Versão | Spark | Python | Destaques | Limitações |
| --- | --- | --- | --- | --- |
| **3.0** | 3.1.1 | 3.7 | Estável, ideal para workloads legados | Menos recursos e integrações modernas |
| **4.0** | 3.3.0 | 3.10 | Suporte a frameworks de data lake (Hudi, Iceberg, Delta Lake), conectores otimizados | ML/PII transforms não disponíveis |
| **5.0** | 3.5.4 | 3.11 | FGAC nativo, requirements.txt, DataZone, S3 Table Bucket, Java 17, SageMaker | Table-level access control via GlueContext não suportado |

### Destaques do Glue 5.0

* Integração com Amazon SageMaker para ML
    
* Suporte atualizado para Hudi 0.15.0, Iceberg 1.7.1, Delta Lake 3.3.0
    
* Controle de acesso refinado (FGAC) com AWS Lake Formation
    
* Suporte a `requirements.txt` para dependências Python
    
* Integração com Amazon DataZone para governança
    
* Suporte a S3 Table Bucket e visualizações multi-dialeto no Data Catalog
    

### Recomendações

* Use Glue 5.0 para novos projetos devido à performance (32% mais rápido que 4.0) e novos recursos.
    
* Mantenha Glue 3.0 para sistemas legados que dependem de Python 3.7.
    
* Verifique periodicamente as release notes para manter-se atualizado com as mudanças e novas funcionalidades.
    

## Tipos de Worker

A seleção do worker correto depende do tamanho e complexidade do seu trabalho. Veja abaixo uma tabela comparativa que pode servir como referência:

```mermaid
graph LR
    subgraph "Worker Types"
        A[G.1X<br/>💰 Custo Eficiente] --> A1[4 vCPU<br/>16GB RAM<br/>94GB Disco]
        B[G.2X<br/>⚖️ Balanceado] --> B1[8 vCPU<br/>32GB RAM<br/>138GB Disco]
        C[G.4X<br/>🚀 Alto Desempenho] --> C1[16 vCPU<br/>64GB RAM<br/>256GB Disco]
    end
    
    subgraph "Use Cases"
        D[📄 Datasets Pequenos<br/>≤10GB]
        E[📊 Datasets Médios<br/>20-100GB]
        F[🗄️ Datasets Grandes<br/>>100GB]
    end
    
    A --> D
    B --> E
    C --> F
    
    style A fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
    style B fill:#1890ff,stroke:#096dd9,stroke-width:2px,color:#fff
    style C fill:#722ed1,stroke:#531dab,stroke-width:2px,color:#fff
```

| Worker | DPU | vCPU | RAM | Disco | Indicação |
| --- | --- | --- | --- | --- | --- |
| **G.1X** | 1 | 4 | 16GB | 94GB | Workloads comuns, joins, transforms, custo eficiente |
| **G.2X** | 2 | 8 | 32GB | 138GB | Dados maiores, jobs mais pesados |
| **G.4X** | 4 | 16 | 64GB | 256GB | Workloads exigentes, grandes joins, transformações complexas |

### Como escolher

* **G.1X:** Para datasets pequenos a médios (até 10GB) ou transformações simples.
    
* **G.2X:** Para datasets maiores (20-100GB) ou jobs com muitos joins e agregações.
    
* **G.4X:** Para datasets muito grandes (&gt;100GB) ou tarefas intensivas, como ML.
    

### Um caso de uso real

Como exemplo prático, um job de produção foi configurado para processar 2,3 milhões de registros em menos de 6 minutos. Para isso, ele utiliza instâncias G.1X com auto-scale ativado, demonstrando alta eficiência e economia. A tarefa busca dados em uma base PostgreSQL, realiza o processamento via API’s do Spark, serializa os registros em Avro e, por fim, publica-os em um tópico do Kafka.

```mermaid
graph LR
    A[🐘 PostgreSQL<br/>2.3M registros] --> B[⚡ AWS Glue<br/>G.1X Auto-Scale]
    B --> C[🔄 Spark Processing<br/>API Transforms]
    C --> D[📦 Avro Serialization]
    D --> E[📡 Kafka]
    
    B -.-> F[⏱️ <6 minutos<br/>💰 Custo otimizado]
    
    style A fill:#336791,stroke:#fff,stroke-width:2px,color:#fff
    style B fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
    style E fill:#231f20,stroke:#fff,stroke-width:2px,color:#fff
    style F fill:#52c41a,stroke:#389e0d,stroke-width:1px,color:#fff
```

> **Dica:** Monitore o Spark UI para ajustar workers com base em gargalos de CPU, memória ou I/O.

## Classe de Execução Flex

Disponível para Glue 3.0+ com workers G.1X ou G.2X, essa configuração oferece uma redução de custos de aproximadamente 34% (com tarifas de $0,29/DPU-hora versus $0,44/DPU-hora) ao custo de uma maior latência na inicialização. Essa opção é ideal para jobs que não exigem respostas imediatas, como relatórios semanais, testes ou tarefas programadas fora do horário de pico, onde a flexibilidade em relação ao tempo de resposta compensa a economia operacional.

```mermaid
graph TB
    subgraph "Execução Standard"
        A[💸 $0.44/DPU-hora] --> A1[🚀 Inicialização Rápida]
        A1 --> A2[⚡ Baixa Latência]
    end
    
    subgraph "Execução Flex"
        B[💰 $0.29/DPU-hora] --> B1[⏳ Inicialização Lenta]
        B1 --> B2[🕐 Maior Latência]
    end
    
    subgraph "Economia"
        C[📊 34% de Redução<br/>de Custos]
    end
    
    B --> C
    
    style A fill:#ff4d4f,stroke:#cf1322,stroke-width:2px,color:#fff
    style B fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
    style C fill:#1890ff,stroke:#096dd9,stroke-width:2px,color:#fff
```

Por exemplo, um job noturno para limpeza e consolidação de dados pode utilizar a opção Flex para reduzir despesas, uma vez que eventuais atrasos na inicialização não impactam significativamente a execução do processo.

## Dimensionamento de Workers

Gerenciar os workers de forma adequada é fundamental para otimizar custos e garantir a performance desejada dos jobs. O dimensionamento incorreto pode levar a custos excessivos e ineficiências, sendo crucial alinhar a alocação de recursos à demanda real do workload para evitar desperdícios e manter a eficiência operacional.

```mermaid
flowchart TD
    A[🤔 Qual tipo de workload?] --> B{Volume de dados<br/>é previsível?}
    
    B -->|Sim| C[📊 Número Fixo de Workers]
    B -->|Não| D[🔄 Auto Scaling]
    
    C --> C1[✅ Previsibilidade de custos<br/>✅ Performance constante<br/>❌ Risco de superdimensionamento]
    
    D --> D1[✅ Otimização automática<br/>✅ Flexibilidade<br/>❌ Latência variável]
    
    D --> E[Configuração]
    E --> E1[--enable-auto-scaling true]
    E --> E2[--min-workers X]
    E --> E3[--max-workers Y]
    
    style A fill:#722ed1,stroke:#531dab,stroke-width:2px,color:#fff
    style C fill:#1890ff,stroke:#096dd9,stroke-width:2px,color:#fff
    style D fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
```

### 1\. Auto Scaling

Ideal para workloads com variação ou imprevisibilidade de carga, como:

* Jobs de streaming
    
* Processos batch mensais com picos de processamento
    
* Processamento de logs ou dados com volume flutuante
    

#### Como Configurar

* **Ativar:** `--enable-auto-scaling true`
    
* **Definir limites:** `--min-workers` e `--max-workers`
    
* **(Opcional) Monitoramento contínuo:** `--enable-continuous-cloudwatch-log true`
    

#### Benefícios

* **Otimização de custos:** Ajusta os recursos automaticamente conforme a demanda.
    
* **Flexibilidade:** Escala horizontalmente de acordo com o volume de dados e complexidade.
    
* **Eficiência:** Reduz ociosidade em períodos de baixa carga.
    

#### Considerações

* Pode haver variação na latência, já que a escalabilidade não é instantânea (tempo de provisionamento dos workers).
    
* Usar workers fixos em jobs com carga variável pode resultar em ociosidade e custo extra.
    

#### Exemplos

* Job mensal com picos de volume: configurar entre 2 e 20 workers garante economia e desempenho.
    
* Job de logs com carga entre 50GB e 1TB: Auto Scaling pode reduzir em até 40% os custos mensais.
    
* Jobs near real-time: monitoramento via CloudWatch permite ajuste em tempo real.
    

### 2\. Número Fixo

Mais indicado para workloads estáveis e previsíveis, como:

* Jobs diários com volume constante
    
* Pipelines críticos onde a performance precisa ser constante
    

#### Como Configurar

Definir manualmente a quantidade de workers com base na análise do job e volume de dados.

#### Benefícios

* **Previsibilidade:** Permite estimar com exatidão o custo e tempo de execução.
    
* **Estabilidade:** Elimina variações causadas por escalabilidade dinâmica.
    

#### Considerações

Risco de superdimensionamento, com desperdício de recursos em cenários de baixa carga.

## Apache Spark

Ao trabalhar com o Glue, entender como o Spark funciona é essencial para extrair o máximo da plataforma, pois ele é utilizado como mecanismo de execução distribuída. Essa combinação oferece uma plataforma robusta para processamento de dados em larga escala, com alta disponibilidade, tolerância a falhas e integração nativa com o ecossistema AWS.

```mermaid
graph LR
    subgraph "📱 Execução Local Python"
        A1[📄 Script Python] --> A2[💾 Dados em Memória<br/>Uma Máquina]
        A2 --> A3[⚡ Processamento Sequencial]
    end
    
    subgraph "🌐 Execução Distribuída PySpark"
        B1[🎯 Driver Program] --> B2[📊 RDD/DataFrame]
        B2 --> B3[🔄 Distribuição de Tasks]
        B3 --> B4[⚡ Executor 1]
        B3 --> B5[⚡ Executor 2]
        B3 --> B6[⚡ Executor N]
        B4 --> B7[💾 Dados Distribuídos<br/>Múltiplas Máquinas]
        B5 --> B7
        B6 --> B7
    end
    
    style A1 fill:#1890ff,stroke:#096dd9,stroke-width:2px,color:#fff
    style B1 fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
    style B4 fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
    style B5 fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
    style B6 fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
```

O Spark executa transformações de dados em paralelo por meio de executores, que são processos responsáveis por realizar as tasks atribuídas pelo driver, utilizando a memória distribuída para acelerar o processamento. Cada executor possui múltiplos slots, normalmente atrelados a núcleos de CPU virtuais (vCPUs), o que permite o processamento simultâneo de diversas tasks.

Esse paralelismo é possível graças ao conceito de RDD (Resilient Distributed Dataset), uma abstração fundamental do Spark que representa uma coleção de dados distribuída, imutável e tolerante a falhas. Os RDDs geralmente são manipulados de forma indireta via DataFrames e DynamicFrames, que adicionam estrutura e semântica aos dados, facilitando operações como schema inference, joins, filtros e agregações.

```mermaid
graph TB
    A[🤔 Escolher Ferramenta ETL] --> B{Tamanho dos dados<br/>e complexidade?}
    
    B -->|Pequeno e Simples<br/><1GB| C[⚡ AWS Lambda]
    B -->|Médio/Grande<br/>ETL Distribuído| D[🔧 AWS Glue Spark]
    B -->|Médio - Script Python<br/>Sem distribuição| E[🐍 Glue Python Shell]
    
    C --> C1[✅ Inicialização rápida<br/>✅ Custo baixo<br/>✅ Event-driven<br/>❌ Limitado a 1GB]
    
    D --> D1[✅ Processamento distribuído<br/>✅ Grande escala<br/>✅ Tolerância a falhas<br/>❌ Cold start alto]
    
    E --> E1[✅ Python puro<br/>✅ Data Catalog integrado<br/>✅ Sem overhead Spark<br/>❌ Não distribuído]
    
    style C fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
    style D fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
    style E fill:#1890ff,stroke:#096dd9,stroke-width:2px,color:#fff
```

Contudo, é importante lembrar que o poder do Spark vem com custo: Apesar de sua potência, o Spark carrega um tempo de inicialização elevado (cold start) e custos proporcionalmente altos para workloads pequenos. Para tarefas simples, como a manipulação de arquivos JSON, CSV ou transformações básicas, o uso do AWS Glue pode ser excessivo. Por exemplo, quando você executa um job Glue apenas com um script Python sequencial (sem usar Spark, DataFrames ou DynamicFrames), você está pagando o custo do motor distribuído (inclusive o tempo de provisionamento dos recursos Spark) mas sem usar o poder dele! Nesses casos, o uso do AWS Lambda surge como uma alternativa mais econômica e com tempo de inicialização significativamente menor. O Lambda é ideal para cargas pequenas (até 1 GB), tarefas event-driven e a execução rápida de scripts Python, especialmente quando a complexidade do processamento é baixa.

Já para situações em que a execução precisa permanecer no ambiente do AWS Glue, por exemplo, devido à integração com o AWS Data Catalog, uso de triggers ou necessidade de orquestração centralizada, o Glue Python Shell representa uma opção mais leve e eficiente, permitindo rodar scripts em Python puro sem o overhead do motor Spark.

Para extrair o máximo desempenho do Spark, considere as seguintes boas práticas:

* Evite ações que trazem todos os dados ao driver, como `collect()` ou `toPandas()`, especialmente com grandes volumes. Essas operações podem gerar estouro de memória e travar o job.
    
* Use transformações distribuídas, como `map`, `filter`, `reduce`, `select`, `withColumn`, que são executadas em paralelo nos executores Spark.
    
* Otimize o particionamento de dados com `repartition` ou `coalesce` para evitar data skew e melhorar o desempenho de leitura e escrita.
    
* Utilize formatos colunares, como Parquet, que são mais eficientes em termos de I/O e armazenamento.
    
* Ajuste o número de executores e núcleos conforme a carga de trabalho esperada, lembrando que cada executor Spark pode executar uma tarefa por núcleo (vCPU).
    
* Habilite ferramentas de monitoramento, como Spark UI e CloudWatch Logs, para diagnosticar problemas de paralelismo, memória e shuffle.
    
* Use checkpoints em S3 para salvar o estado intermediário em jobs longos, garantindo maior resiliência em caso de falhas.
    
* Implemente políticas de retry com backoff exponencial para jobs críticos, evitando reprocessamentos constantes e falhas em cascata.
    
* Defina um timeout ligeiramente acima do tempo esperado, para evitar custos com jobs travados.
    
* Valide jobs com dados amostrais em ambientes de desenvolvimento antes de escalar para produção.
    

Para aprofundar ainda mais no ajuste fino de performance, a AWS disponibiliza um guia completo com práticas recomendadas. O documento aborda desde os fundamentos da arquitetura distribuída e avaliação preguiçosa, até estratégias avançadas de particionamento, otimização de embaralhamentos (shuffles), paralelismo, tuning de cluster e análise de métricas. Esse material é altamente recomendado para quem busca elevar a eficiência de pipelines Glue em ambientes de produção.

[Acesse o documento completo aqui: Práticas recomendadas para ajuste de desempenho AWS Glue para tarefas do Apache Spark (AWS Docs)](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-apache-spark-tuning.html)

## Monitoramento Proativo e Alertas com New Relic

Para garantir a estabilidade e o desempenho dos jobs, é essencial contar com um monitoramento eficaz. Com a integração do New Relic e o AWS CloudWatch Metric Streams, você consegue acompanhar métricas críticas dos jobs e configurar alertas que permitem uma resposta imediata a qualquer comportamento incomum. Essa integração facilita a personalização de dashboards e a automação dos alertas, garantindo que sua equipe seja notificada via OpsGenie ou Slack sempre que os parâmetros monitorados ultrapassarem os limites predefinidos.

```mermaid
graph TB
    subgraph "AWS Environment"
        A[⚡ AWS Glue Jobs] --> B[📊 CloudWatch Metrics]
        B --> C[🌊 CloudWatch Metric Streams]
    end
    
    subgraph "New Relic Platform"
        C --> D[📈 New Relic Dashboard]
        D --> E[🚨 Alert Policies]
        E --> F[📧 Notification Channels]
    end
    
    subgraph "Team Communication"
        F --> G[📱 OpsGenie]
        F --> H[💬 Slack]
    end
    
    subgraph "Key Metrics"
        I[📥 bytesRead<br/>Volume de dados]
        J[❌ numFailedTasks<br/>Tarefas falhadas]
        K[🔄 shuffleBytesWritten<br/>Operações shuffle]
        L[⏱️ elapsedTime<br/>Tempo execução]
    end
    
    D --> I
    D --> J
    D --> K
    D --> L
    
    style A fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
    style D fill:#1ce783,stroke:#008c99,stroke-width:2px,color:#fff
    style G fill:#172b4d,stroke:#fff,stroke-width:2px,color:#fff
    style H fill:#4a154b,stroke:#fff,stroke-width:2px,color:#fff
```

Alguns exemplos de métricas que podem ser utilizadas para monitorar os jobs do AWS Glue incluem:

* `glue.driver.aggregate.bytesRead`: Total de bytes lidos de todas as fontes de dados durante a execução dos jobs, refletindo o volume de dados processados.
    
* `glue.driver.aggregate.numFailedTasks`: Quantidade de tarefas que falharam durante a execução, permitindo identificar rapidamente pontos de falha.
    
* `glue.driver.aggregate.shuffleBytesWritten`: Número de bytes escritos durante operações de shuffle, o que pode indicar problemas relacionados a particionamento dos dados.
    
* `glue.driver.aggregate.elapsedTime`: Tempo total de execução do job (em milissegundos, excluindo o tempo de inicialização), importante para acionar alertas quando o tempo de processamento ultrapassar os limites estabelecidos.
    

```mermaid
flowchart LR
    subgraph "🔄 Ciclo de Monitoramento"
        A[⚡ Job AWS Glue<br/>Executando] --> B[📊 Métricas<br/>CloudWatch]
        B --> C[🌊 Metric Streams<br/>Tempo Real]
        C --> D[📈 New Relic<br/>Dashboard]
        
        D --> E{🚨 Threshold<br/>Ultrapassado?}
        E -->|Não| F[✅ Monitoramento<br/>Contínuo]
        E -->|Sim| G[📢 Alerta<br/>Disparado]
        
        G --> H[📱 Notificação]
        H --> I[👥 Equipe<br/>Acionada]
        I --> J[🔧 Ação<br/>Corretiva]
        
        F --> A
        J --> K[📝 Análise<br/>Pós-Incidente]
        K --> L[⚙️ Ajuste<br/>Thresholds]
        L --> A
    end
    
    style A fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
    style D fill:#1ce783,stroke:#008c99,stroke-width:2px,color:#fff
    style E fill:#722ed1,stroke:#531dab,stroke-width:2px,color:#fff
    style G fill:#ff4d4f,stroke:#cf1322,stroke-width:2px,color:#fff
    style H fill:#52c41a,stroke:#389e0d,stroke-width:2px,color:#fff
```

Esses são alguns dos benefícios e funcionalidades da integração:

* **Análise de Tendências:** Monitore o histórico de execução dos jobs para ajustar proativamente os thresholds. A análise dos dados históricos possibilita a identificação antecipada de problemas e a otimização contínua dos processos, melhorando a performance geral antes que os problemas se agravem.
    
* **Dashboards Personalizados:** Crie dashboards dedicados para visualizar, em tempo real, as métricas dos seus jobs. Isso facilita a identificação de padrões, tendências e eventuais desvios que possam impactar a performance dos processos.
    
* **Alertas Compostos:** Combine múltiplas métricas, como erros, volume de dados e tempo de execução, em um único alerta. Essa abordagem reduz o ruído e direciona a atenção da equipe para eventos críticos, garantindo uma resposta mais rápida e eficaz.
    
* **Integração com OpsGenie e Slack:** Configure a entrega de alertas por meio do OpsGenie ou diretamente em canais do Slack. Essa integração agiliza a comunicação entre as equipes, permitindo coordenação imediata e organizada diante de incidentes.
    

## TL;DR

* **Escolha a versão correta do Glue:** Glue 5.0 oferece os recursos mais recentes, mas versões anteriores podem ser adequadas para workloads legados.
    
* **Selecione o worker apropriado:** Use G.1X para jobs leves e G.4X para tarefas pesadas, ajustando conforme o tamanho e complexidade dos dados.
    
* **Considere a classe Flex:** Para jobs não críticos, a execução Flex reduz custos em cerca de 34%.
    
* **Use auto scaling para workloads variáveis:** Ajusta recursos dinamicamente, economizando em picos e vales de processamento.
    
* **Monitore e otimize:** Ative Spark UI e CloudWatch para identificar gargalos e reduzir custos.
    
* **Glue vs. Lambda:** Prefira Glue para ETL distribuído e Lambda para tarefas simples e rápidas.
