O Timeout que funcionava na minha máquina: como diagnosticamos SNAT Port Exhaustion no Azure

O Timeout que funcionava na minha máquina: como diagnosticamos SNAT Port Exhaustion no Azure

26 de Fevereiro de 2026

Semana passada tivemos instabilidade em uma das nossas aplicações. Timeouts intermitentes, usuários reclamando, e o pior: nenhuma mudança recente no código.

Se você já passou por isso, sabe o desespero. Quando não há deploy recente para culpar, a investigação pode ir para qualquer direção.

A Pista Falsa

Nas análises iniciais, encontramos alguns locks no banco de dados. As tabelas envolvidas eram justamente as da mesma rota que estava causando os timeouts. Parecia fazer sentido: locks no banco → queries lentas → timeout.

Seguimos essa direção. Analisamos queries, índices, planos de execução. Gastamos tempo precioso.

Lição aprendida: correlação não é causação. Só porque dois problemas aparecem juntos não significa que um causa o outro.

A Sala de Guerra

Hoje pela manhã, como o problema persistia, montamos uma sala de guerra com os envolvidos. Às vezes é isso que precisamos: parar, respirar, e olhar o problema com mais calma.

Ao analisar os logs novamente, percebi algo que tinha passado despercebido: o timeout não era no banco. Era na chamada de uma API externa.

Pontuei isso para o time, e então veio a frase que mudou tudo:

"Mas quando eu chamo direto da minha máquina eu consigo gerar várias vezes sem erro. O problema parece ser apenas no Azure."

BINGO.

Quando algo funciona local mas falha no Azure, especialmente em App Service, existe um suspeito clássico: SNAT Port Exhaustion.

O que é SNAT Port Exhaustion?

Quando seu App Service precisa fazer uma chamada de saída (para uma API externa, por exemplo), ele não usa seu próprio IP. O Azure usa SNAT (Source Network Address Translation) para rotear o tráfego através de um pool compartilhado de IPs e portas.

O problema é que esse pool é limitado. Cada instância do App Service tem aproximadamente 128 portas SNAT disponíveis para conexões com o mesmo endpoint de destino.

Pense assim:

  • Sua aplicação precisa chamar api.exemplo.com:443
  • Cada conexão TCP ativa usa uma porta SNAT
  • Se você abrir muitas conexões simultâneas (ou não fechá-las corretamente), as portas acabam
  • Novas conexões falham com timeout

Por que funciona na sua máquina? Porque seu computador tem seu próprio pool de portas efêmeras (geralmente 16.000+). No App Service, você compete por um pool compartilhado e muito menor.

Como Diagnosticar

Agora que sabemos o que procurar, vamos às ferramentas.

1. Azure Monitor Metrics

No portal do Azure, acesse seu App Service → Metrics e adicione:

  • SNAT Connection Count: número de conexões SNAT ativas
  • SNAT Connection Failed Count: conexões que falharam por falta de portas

Se você vê Failed Count subindo, é confirmação do problema.

2. Diagnose and Solve Problems

No blade do App Service, clique em Diagnose and solve problems. O Azure tem detectores automáticos para SNAT exhaustion:

  • Procure por "TCP Connections" ou "SNAT"
  • O detector mostra gráficos de conexões por estado (Established, Time Wait, etc.)
  • Muitas conexões em TIME_WAIT indicam que conexões não estão sendo reutilizadas

3. Application Insights

Se você usa Application Insights, analise:

  • Dependency calls: procure por chamadas com alta latência ou falhas para o mesmo endpoint
  • Performance: veja se há correlação entre picos de requisições e timeouts nas dependências
  • Failures: filtre por exceptions de timeout em chamadas HTTP

4. Kudu / Advanced Tools

Para uma análise mais profunda:

  1. Acesse https://seuapp.scm.azurewebsites.net
  2. Vá em Debug console → CMD
  3. Execute: netstat -ano | findstr ESTABLISHED

Muitas conexões para o mesmo IP externo? Provavelmente SNAT exhaustion.

Causas Comuns

O problema geralmente está no código:

  • HttpClient instanciado diretamente: cada new HttpClient() pode criar uma nova conexão. Use IHttpClientFactory.
  • Conexões não descartadas: se você não fecha conexões corretamente, elas ficam em TIME_WAIT por até 4 minutos.
  • Alto volume para mesmo endpoint: mesmo com código correto, um volume muito alto de chamadas para a mesma API pode esgotar as portas.

Corrigir o código é importante, mas às vezes você precisa de uma solução de infraestrutura.

A Solução: VNet Integration + NAT Gateway

Para resolver definitivamente o problema de SNAT exhaustion, a solução recomendada pela Microsoft é usar VNet Integration com NAT Gateway.

Por que funciona?

Na arquitetura padrão, seu App Service usa o pool compartilhado de SNAT do Azure Load Balancer. É limitado e você não tem controle.

Com NAT Gateway:

  • Cada IP público do NAT Gateway fornece 64.000 portas SNAT
  • Você pode ter até 16 IPs públicos = mais de 1 milhão de portas
  • As portas são alocadas sob demanda, não fixas por instância
  • Você tem controle sobre o timeout (4-120 minutos)

Arquitetura

App Service → VNet Integration → Subnet → NAT Gateway → Internet/API Externa

O tráfego de saída do App Service passa pela sua VNet e sai pelo NAT Gateway, que tem um pool de portas muito maior.

Implementação

  1. Criar uma VNet com uma subnet dedicada para integração

    • A subnet precisa ter pelo menos /26 (64 endereços)
    • Essa subnet será usada exclusivamente pelo App Service
  2. Criar o NAT Gateway

    • Crie um IP público (ou mais, se precisar de mais portas)
    • Crie o NAT Gateway e associe o IP público
  3. Associar o NAT Gateway à subnet

    • Na configuração da subnet, selecione o NAT Gateway criado
  4. Habilitar VNet Integration no App Service

    • App Service → Networking → VNet Integration
    • Selecione a VNet e subnet criadas
  5. Rotear todo tráfego pela VNet

    • Em Configuration, adicione: WEBSITE_VNET_ROUTE_ALL=1
    • Isso garante que TODO tráfego de saída use o NAT Gateway

Considerações de Custo

NAT Gateway tem custo:

  • Por hora de provisionamento (~R$ 0,20/hora)
  • Por GB de dados processados (~R$ 0,20/GB)

Para aplicações com alto volume de chamadas externas, o custo se paga pela estabilidade. Compare com o custo de downtime e horas de investigação.

Lições Aprendidas

  1. Quando funciona local mas não no Azure → pense em limites da plataforma. SNAT exhaustion é o exemplo clássico, mas existem outros (file handles, threads, etc.).

  2. Não confie na primeira correlação. Os locks no banco eram reais, mas não eram a causa. Investigue até ter certeza.

  3. Sala de guerra funciona. Às vezes você precisa de múltiplas perspectivas olhando o mesmo problema.

  4. Soluções de código e infraestrutura são complementares. Use IHttpClientFactory E considere NAT Gateway. Um não substitui o outro.


Referências

Para se aprofundar no tema e implementar a solução:

Diagnóstico e Troubleshooting

VNet Integration

NAT Gateway

Boas Práticas de Código


Já enfrentou SNAT exhaustion? Compartilhe sua experiência nos comentários.

Confira mais:

Fique por dentro das novidades

Assine nossa newsletter e receba as últimas atualizações e artigos diretamente em seu email.

Assinar gratuitamente