Cost-aware architecture: otimizando custos em cloud nativa

1. Fundamentos da Arquitetura Cost-aware

1.1. O paradoxo do custo em cloud: elasticidade vs. desperdício

A promessa da nuvem é pagar apenas pelo que usar. Na prática, a elasticidade sem governança gera desperdício. Estudos indicam que empresas desperdiçam entre 30% e 45% de seus gastos em cloud. O paradoxo surge porque a facilidade de provisionar recursos incentiva o over-provisioning, enquanto a complexidade de monitorar cada componente dificulta a otimização contínua.

1.2. Diferença entre otimização reativa e proativa

FinOps (Financial Operations) é uma disciplina reativa: você analisa faturas, identifica picos e ajusta recursos. Cost-aware Architecture é proativa: o custo é um requisito não-funcional desde o design. Enquanto FinOps pergunta "como reduzir a conta deste mês?", a arquitetura cost-aware pergunta "como projetar este sistema para que cada requisição tenha um custo previsível e mínimo?".

1.3. Métricas-chave

  • Unit Economics: custo por transação, por usuário ativo ou por requisição. Exemplo: R$ 0,0002 por chamada de API.
  • TCO (Total Cost of Ownership): inclui custos de desenvolvimento, operação, migração e descomissionamento.
  • Waste Ratio: percentual de recursos provisionados mas não utilizados. Idealmente abaixo de 10%.
# Exemplo de cálculo de unit economics
Custo mensal total: R$ 5.000
Requisições processadas: 25.000.000
Custo por requisição: R$ 5.000 / 25.000.000 = R$ 0,0002

2. Padrões de Design para Eficiência de Custo

2.1. Serverless-first

Funções serverless (AWS Lambda, Azure Functions, Google Cloud Functions) eliminam custo ocioso. Você paga apenas pelo tempo de execução e memória alocada. Para workloads com picos imprevisíveis ou baixa frequência, serverless reduz drasticamente o waste ratio.

# Configuração de função Lambda com custo otimizado
aws lambda create-function \
  --function-name process-order \
  --runtime python3.12 \
  --memory-size 256 \
  --timeout 30 \
  --reserved-concurrent-executions 10

2.2. Stateless services e auto-scaling granular

Serviços stateless permitem escalar horizontalmente sem complexidade de estado compartilhado. Use Horizontal Pod Autoscaler (HPA) com métricas de custo, não apenas CPU/memória.

# HPA configurado para escalar baseado em requisições por segundo
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-gateway-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-gateway
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Pods
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: 100

2.3. Arquitetura baseada em filas e batch processing

Processamento em lote suaviza picos de demanda. Em vez de provisionar recursos para o pico máximo, use filas (SQS, RabbitMQ) para acumular requisições e processá-las em ritmo constante.

# Configuração de fila SQS com batch processing
aws sqs create-queue \
  --queue-name orders-queue \
  --attributes '{
    "DelaySeconds": "0",
    "MaximumMessageSize": "262144",
    "VisibilityTimeout": "300",
    "ReceiveMessageWaitTimeSeconds": "20"
  }'

3. Otimização de Armazenamento e Dados

3.1. Tiering inteligente

Dados têm ciclos de vida. Armazene dados recentes (hot) em SSD, dados de acesso semanal (warm) em HDD, e dados históricos (cold) em armazenamento de arquivamento. Lifecycle policies automatizam essa transição.

# Política de lifecycle no S3 para tiering automático
{
  "Rules": [
    {
      "Id": "tiering-rule",
      "Status": "Enabled",
      "Transitions": [
        {
          "Days": 30,
          "StorageClass": "STANDARD_IA"
        },
        {
          "Days": 90,
          "StorageClass": "GLACIER"
        }
      ],
      "Expiration": {
        "Days": 365
      }
    }
  ]
}

3.2. Formatos colunares e compressão

Formatos como Parquet e ORC reduzem o armazenamento em até 75% comparado a CSV ou JSON. Além disso, aceleram consultas analíticas, reduzindo custos de computação.

# Conversão de dados para Parquet com PySpark
from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("optimize").getOrCreate()
df = spark.read.csv("s3://raw-data/orders/")
df.write.parquet("s3://optimized-data/orders/", mode="overwrite")

3.3. Caching estratégico

CDN para conteúdo estático, Redis para sessões e consultas frequentes, e memcached para resultados de cálculos pesados. Cada cache evita processamento redundante.

# Configuração de cache Redis com TTL otimizado
import redis

cache = redis.Redis(host='redis-cluster', port=6379, decode_responses=True)
cache.setex("user:123:profile", 3600, serialized_data)

4. Gerenciamento de Recursos Computacionais

4.1. Spot instances e savings plans

Spot instances oferecem descontos de até 90% para workloads tolerantes a falhas. Savings Plans e Reserved Instances garantem descontos de 30-60% para workloads previsíveis.

# Solicitação de spot instance no AWS EC2
aws ec2 request-spot-instances \
  --instance-count 5 \
  --type "one-time" \
  --launch-specification '{
    "ImageId": "ami-0c55b159cbfafe1f0",
    "InstanceType": "t3.medium",
    "Placement": {"GroupName": "batch-group"}
  }'

4.2. Right-sizing contínuo

Perfile workloads por 30 dias para identificar instâncias superdimensionadas (CPU < 20%) ou subdimensionadas (CPU > 80%). Ferramentas como AWS Compute Optimizer ou Azure Advisor sugerem ajustes.

# Comando para análise de right-sizing com AWS CLI
aws compute-optimizer get-ec2-instance-recommendations \
  --instance-arns arn:aws:ec2:us-east-1:123456789:instance/i-12345

4.3. Kubernetes cost optimization

Use node pools heterogêneos (spot + on-demand) e cluster autoscaler para ajustar automaticamente o número de nós.

# Configuração de node pool com spot instances no GKE
gcloud container node-pools create spot-pool \
  --cluster my-cluster \
  --machine-type e2-standard-4 \
  --spot \
  --enable-autoscaling \
  --min-nodes 1 \
  --max-nodes 10

5. Redes e Transferência de Dados

5.1. Minimizando custos de egress

Custos de saída de dados (egress) podem superar custos de computação. Use VPC endpoints para serviços AWS, NAT gateways compartilhados e peering entre VPCs na mesma região.

# Criação de VPC endpoint para S3
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-12345 \
  --service-name com.amazonaws.us-east-1.s3 \
  --route-table-ids rtb-12345

5.2. Data locality

Processe dados onde eles estão armazenados. Evite mover grandes volumes entre regiões. Use data lakes regionais e processamento local.

5.3. Compressão de payload

Comprima respostas HTTP e mensagens de fila. Gzip reduz tráfego em até 70%.

# Middleware de compressão em Node.js
const compression = require('compression');
app.use(compression({ level: 6, threshold: 1024 }));

6. Observabilidade e Governança de Custos

6.1. Tagging estratégico

Tags permitem alocar custos por equipe, serviço, ambiente e projeto. Sem tags, a fatura é uma caixa-preta.

# Tagging de recursos no Terraform
resource "aws_instance" "web" {
  ami           = "ami-12345"
  instance_type = "t3.micro"
  tags = {
    Name        = "web-server"
    Environment = "production"
    Team        = "platform"
    CostCenter  = "CC-123"
  }
}

6.2. Budgets e shutdown automático

Configure budgets no provedor de cloud para alertar quando os gastos excederem 80%, 90% e 100% do orçamento. Ambientes dev/staging devem ter shutdown automático fora do horário comercial.

# Budget no AWS Budgets
aws budgets create-budget \
  --account-id 123456789 \
  --budget '{
    "BudgetName": "monthly-production",
    "BudgetLimit": {"Amount": 5000, "Unit": "USD"},
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST"
  }'

6.3. Anomaly detection

Ferramentas como AWS Cost Anomaly Detection ou CloudHealth identificam picos inesperados. Monitore unit economics em dashboards.

7. Casos de Uso e Antipadrões

7.1. Exemplo prático: migração cost-aware

Uma startup migrou de monólito (R$ 12.000/mês em 4 instâncias EC2) para microserviços com serverless + spot instances. Resultado: R$ 3.500/mês, redução de 70%.

# Arquitetura final
- API Gateway (serverless) -> Lambda (serverless) -> DynamoDB (on-demand)
- Batch processing: ECS Fargate com spot instances
- Storage: S3 com lifecycle para dados frios

7.2. Antipadrão: over-provisioning

Provisionar 10 instâncias "para garantir performance" quando 3 seriam suficientes. Custo 3x maior. Solução: auto-scaling com métricas realistas.

7.3. Antipadrão: ignorar custos de dados em eventos

Arquiteturas orientadas a eventos podem gerar milhões de mensagens. Cada mensagem em filas (SQS, EventBridge) tem custo. Sem governança, custos disparam.

Referências