Cobranças inesperadas de egress: de onde vêm as contas de bandwidth
As cobranças inesperadas de egress geralmente têm origem em quatro hábitos: servir media pela aplicação, não definir cache headers, APIs excessivamente comunicativas e tráfego entre regiões. Encontre a origem e reduza a conta sem mudar de provedor.
A conta chega e está quatro vezes maior do que você esperava. A linha de compute está mais ou menos dentro do orçamento. A que não está é a de egress — os bytes que saem da sua infraestrutura — e há uma boa chance de você nunca ter pensado nisso.
As cobranças inesperadas de egress são a surpresa de billing mais comum no hosting de aplicações, e o motivo é estrutural: nada no seu ciclo de desenvolvimento mede bytes. O seu laptop não cobra por eles. O staging não tem utilizadores. A primeira vez que o bandwidth se torna visível é numa fatura — e, nessa altura, você já colocou em produção o hábito que causou o problema.
Veja de onde ele realmente vem, por ordem de frequência.
1. Servir media pela aplicação
Este caso supera os outros de longe e quase sempre acontece por acidente.
Você coloca um vídeo em /public para fazer uma demo. Funciona, então fica lá. Agora, cada visualização de página transmite esse ficheiro para fora do seu container. Um vídeo de 40 MB numa página com mil visitantes por mês representa 40 GB — provenientes de um ficheiro que você considerava apenas um placeholder.
O mesmo se aplica a imagens de produto, PDFs, uploads de utilizadores e ficheiros de fontes. Nenhum deles parece uma decisão de infraestrutura quando você os adiciona.
A solução não é sofisticada: media estática deve ficar num object storage atrás de uma CDN, não no filesystem da sua aplicação. A sua aplicação deve servir HTML e JSON. No momento em que começa a servir uma imagem hero de 4 MB para cada visitante, está a fazer o trabalho de uma CDN sem beneficiar da economia de uma CDN.
2. Ausência de cache headers
Se as suas respostas não têm cache headers, cada visitante descarrega todos os assets em cada carregamento de página. Os visitantes recorrentes descarregam tudo novamente. Um crawler descarrega os mesmos ficheiros dezenas de vezes por dia.
# Fingerprinted build assets never change — cache them for a year
Cache-Control: public, max-age=31536000, immutable
# HTML changes — revalidate but allow a short window
Cache-Control: public, max-age=0, must-revalidate
# Anything user-specific
Cache-Control: private, no-store
Esta é uma alteração de uma linha por classe de resposta que costuma eliminar a maior parte de uma conta de bandwidth, porque o tráfego removido é pura repetição.
3. APIs que devolvem mais do que o cliente utiliza
Um endpoint de listagem que devolve objetos completos quando a UI apresenta três campos está a enviar a diferença em todos os pedidos, para sempre. Isto nunca aparece no profiling porque é rápido — é apenas grande.
Verifique duas coisas nos seus endpoints mais utilizados:
- A compressão está ativa?
Content-Encoding: gzipoubrem JSON normalmente reduz o tamanho em 70–80%. É uma linha de middleware e frequentemente está em falta. - Está a enviar campos que ninguém lê? Serializar a linha inteira porque o ORM tornou isso fácil é o comportamento predefinido da maioria das codebases.
Um cliente que faz polling agrava ambos os problemas por um fator equivalente ao número de vezes que faz polling por minuto.
4. Tráfego entre regiões e entre serviços
Se a sua aplicação está numa região e a base de dados noutra, todos os resultados das queries atravessam uma fronteira cobrada. É fácil fazer isto por acidente — você cria primeiro a base de dados, escolhe uma região sem pensar e coloca a aplicação noutro local semanas mais tarde.
O tráfego entre os seus próprios serviços também pode ser egress se sair da rede privada e voltar através de um hostname público. Dois serviços no mesmo workspace a comunicar pelos seus URLs públicos estão a pagar duas vezes por uma conversa que nunca precisou de sair da rede.
No Dockup, é difícil cometer este erro específico, porque os serviços referenciam-se pelo nome interno. Um serviço acede a main-db.internal:5432 e a outro serviço através do alias <slug>.internal — o tráfego que permanece dentro da rede do workspace nunca toca num listener público. É também por isso que a base de dados não tem um hostname público por predefinição: não há nada para encaminhar acidentalmente através da rede pública.
Encontrar a origem em vez de adivinhar
Adivinhar qual dos quatro casos é responsável desperdiça um ciclo de billing. Faça medições:
Leia o access log por bytes, não por contagem. Ordene as respostas principais pelo total de bytes servidos, e não pelo número de pedidos. O endpoint que envia mais dados raramente é o mais chamado.
Verifique os maiores assets estáticos. Se algum ficheiro com mais de um megabyte está a ser servido pela sua aplicação, essa deve ser a primeira coisa a mover.
# What is the service actually doing right now
dockup metrics my-project/my-api --json
# And what is it logging
dockup logs my-project/my-api -n 1000
Fique atento aos crawlers. Um bot com comportamento incorreto que descarrega ficheiros grandes repetidamente pode representar a maior parte do egress de um mês num site com tráfego humano moderado. robots.txt e um noindex em ambientes de preview são medidas simples.
Os ambientes que ninguém contabiliza
Dois hábitos geram egress que nunca aparece no modelo mental de ninguém:
Ambientes de preview. Um preview por pull request é realmente útil e multiplica silenciosamente a sua infraestrutura. Cinco PRs abertas significam cinco cópias da sua stack, cada uma com o seu próprio tráfego — frequentemente dos mesmos crawlers, porque os URLs de preview são indexados quando você não os bloqueia.
Staging de longa duração. Um staging que está ativo há oito meses, que ninguém visita, continua a fazer pull de images, continua a ser rastreado e continua a executar os seus cron jobs.
Nenhum dos dois é motivo para deixar de os utilizar. Ambos são motivo para impor limites: expire os previews quando o PR for fechado e marque-os com noindex para que os motores de pesquisa deixem de os descarregar por sua conta.
dockup noindex my-project/my-api --on
Como deve ser um bom billing
Você deve conseguir responder a três perguntas antes de a fatura chegar:
- O que está atualmente em execução? Incluindo aquilo de que se esqueceu.
- O que cada componente consumiu? Separado entre compute e transferência, e não apresentado como um único número.
- O que acontece se houver um pico? Um limite que interrompe serviços é desagradável. Um limite inexistente é pior.
O Dockup mede a infraestrutura separadamente do plano, por isso a taxa do plano não disfarça o uso — e o crédito de $20 do plano Pro é aplicado a esse uso, em vez de ser um desconto na taxa. O importante é conseguir ver claramente o que corresponde a cada parte.
A versão curta
Mova a media para object storage. Defina cache headers. Ative a compressão. Mantenha os serviços e as respetivas bases de dados na mesma região e permita que comuniquem pela rede privada, em vez da internet pública. Expire os ambientes de preview e mantenha-os fora dos resultados de pesquisa.
Estes cinco hábitos resolvem praticamente todas as surpresas relacionadas com contas de bandwidth, e nenhum deles exige mudar o local onde faz hosting.
Perguntas frequentes
O que é egress? São os dados que saem da sua infraestrutura em direção à internet. Respostas para utilizadores, ficheiros descarregados e payloads de API. O tráfego de entrada normalmente é gratuito; o de saída, geralmente não.
Porque é que a minha conta de egress é maior do que a de compute? Quase sempre porque a aplicação está a servir ficheiros que deveriam estar numa CDN. Um único asset grande numa página popular pode representar mais tráfego do que semanas de processamento de pedidos.
Uma CDN reduz mesmo estes custos? Sim, quando faz cache. A origem serve o ficheiro uma vez por edge, em vez de uma vez por visitante, e o preço por gigabyte da CDN é normalmente uma fração do praticado por uma plataforma de aplicações.
Os ambientes de preview custam tanto como a produção? Custam aquilo que consomem, o que frequentemente é mais do que o esperado porque cada um é uma cópia completa e os URLs de preview são rastreados quando isso não é impedido.
