AWS para um time pequeno: chato de propósito, 35% mais barato

TL;DR - Numa plataforma multi-tenant tocada por um time pequeno, escolhi serviços da AWS que o time consegue operar às 3 da manhã: ECS com auto scaling, RDS, SQS/SNS, CloudFront e alarmes no CloudWatch. Depois fui atrás da conta com quatro alavancas (rightsizing, Savings Plans, Spot para os workers e desligar o que não é produção à noite) e cortei 35% do custo mensal.


A plataforma que eu lidero é um sistema multi-tenant de gestão de ativos. Ela integra com o ERP dos clientes e com sistemas do setor público, e tem um app mobile usado em campo. O time é pequeno e todo mundo mexe em backend, frontend e mobile. Ninguém tem tempo pra ficar cuidando de cluster Kubernetes.

Então a primeira pergunta da arquitetura não foi “qual a melhor stack”. Foi “quem conserta isso quando quebrar, e em quanto tempo”.

O que escolhi e por quê

  • ECS com auto scaling para as APIs e os workers. Sem cluster pra administrar, deploy é uma task definition nova, rollback é a anterior.
  • RDS PostgreSQL com backup automático. Um banco só, um conjunto de conhecimento só.
  • SQS e SNS entre a API e tudo que é lento: integrações com ERP e setor público, geração de relatório, importação em massa. A API responde rápido e o worker leva o tempo que precisar. O SNS espalha um evento para os consumidores que se importam com ele.
  • CloudFront na frente do app web e dos arquivos estáticos.
  • Alarmes no CloudWatch no que acorda alguém: idade da fila, taxa de 5xx, restart de task, CPU e conexões do banco.
flowchart LR
  Users[Web e mobile] --> CF[CloudFront]
  CF --> ALB[Load balancer]
  ALB --> API[API no ECS, auto scaling]
  API --> RDS[(RDS PostgreSQL)]
  API --> SNS[Tópicos SNS]
  SNS --> SQS[Filas SQS]
  SQS --> Workers[Workers no ECS]
  Workers --> Ext[ERP e sistemas do setor público]
  CW[Alarmes CloudWatch] -.-> API
  CW -.-> SQS

A regra que moldou tudo: qualquer coisa que depende de um sistema que a gente não controla passa por uma fila. ERP e sistema de governo caem, ficam lentos e mudam de comportamento sem aviso. Se a API chamasse direto, o dia ruim deles virava o nosso. Com uma fila no meio, uma integração lenta vira uma fila crescendo e um alarme no CloudWatch, não um app lento para todos os tenants.

Cortando 35% da conta

Com a plataforma estável, abri a conta linha por linha. Não teve uma grande correção. Foram quatro bem sem graça:

  1. Rightsizing. A maioria das tasks e o banco estavam dimensionados para um pico que nunca veio. Olhei CPU e memória de algumas semanas no CloudWatch e cortei o que estava ocioso.
  2. Savings Plans para a base que roda o tempo todo. Com o tamanho certo, se comprometer com ele é dinheiro de graça.
  3. Spot para os workers. Consumidor de fila pode ser interrompido e tentar de novo, então é o lugar certo para capacidade Spot. A API fica em capacidade normal.
  4. Desligar o que não é produção à noite e no fim de semana. Staging e dev não precisam rodar quando ninguém está trabalhando.

A ordem importa. Se você contrata Savings Plans antes do rightsizing, trava o desperdício.

O que eu diria pra outro tech lead

Escolha a arquitetura que o seu time consegue debugar, coloque uma fila na frente de todo sistema externo e crie alarme de idade de fila antes de qualquer outro. Depois leia a conta como você lê os logs. A economia estava ali o tempo todo; só ninguém tinha olhado.