> ## Content Index
> Fetch the complete content index at: https://www.azurebrasil.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Quando o APM te engana: Um milhão de requisições e um gargalo invisível no TCP
- URL: https://www.azurebrasil.cloud/blog/quando-o-apm-te-engana-um-milhao-de-requisicoes-e-um-gargalo-invisivel-no-tcp/
- Published: 2025-11-14T16:04:29.000Z
- Updated: 2026-03-19T14:06:48.000Z
- Description: Você entende as limitações que sua incrivel stack de observalidade tem? Não por descuido. É limitação técnica mesmo.
- Author: Bruno Brito
- Tags: networking, #developer, case

Um cliente processa **milhões de transações de pagamento por dia**. Só com um dos parceiros dele, são cerca de **1 milhão** de requisições diárias.

E, deste volume, algo estranho acontecia.

**Aproximadamente 1.000 requisições apresentavam mais de 3 segundos de resposta**, algumas chegando a 10 segundos! E aparentemente **sem nenhum padrão** que pudesse determinar a causa.

No mesmo segundo em que uma transação demorava 10 segundos, outra era processada em **200 ms**.

Clássico cenário de caos distribuído.

O parceiro dizia que não era problema dele.  
Nosso cliente dizia que não era ele.  
E ambos apontavam para um mesmo ponto de "verdade":

> O APM disse que a requisição levou 10 segundos. Logo, é problema do outro lado.

E então fomos chamados.

## War Room montada

Chegamos para ajudar a formar evidências sólidas o suficiente para que o parceiro dele não pudesse se "esconder".

Depois da explicação do cenário, fizemos a primeira pergunta:

– **Qual linguagem vocês usam?**  
O cliente, já sem paciência e sem entender o motivo da pergunta:  
– *Python. Por quê?*  
– Como o Python gerencia conexões HTTP?  
– *Não estou entendendo como isso ajuda.*  
– Queremos saber se o Python está reutilizando conexões ou se está **refazendo handshake TCP** a cada requisição.  
– *Mas se isso fosse o problema, por que só algumas chamadas são lentas?*

Excelente pergunta.

Respondemos:

– E se essas requisições lentas aconteceram justamente quando **uma instância reiniciou** e precisou refazer **resolução DNS**?

– E se, no momento do handshake, o servidor do parceiro estava sobrecarregado por **meio segundo**?

– Ou se houve uma retransmissão TCP na camada 4 que o APM não captura?

Nesse ponto o cliente **parou, respirou e prestou atenção**.  
Finalmente estávamos falando de algo que ele nunca tinha considerado.

Afinal, qual dev olha pra rede?

## O problema clássico da Observabilidade

A raiz desse problema pode estar na **limitação estrutural** dos sistemas de observabilidade:

O APM só vê **o processo da aplicação**.

Quando o código executa:

```python
httpRequest.send()

```

O APM começa a contar o tempo.  
Mas tudo que acontece **fora** do processo da aplicação e que compõe a maior parte da chamada HTTP ele não vê.

Isso inclui:

- Resolução DNS
- Handshake TCP (SYN, SYN/ACK, ACK)
- Abertura da porta efêmera (ex: 62340)
- Retransmissões de pacotes
- Concorrência no driver de rede
- Filas internas do kernel
- Latência real na camada 4 ou na camada 3
- Timeout de SYN/ACK
- Slow start do TCP

O APM só vê o que a **linguagem** vê.  
E a linguagem só vê o que o **processo da aplicação** vê.

Resultado?

Se a requisição ficou presa dentro do sistema operacional, o APM vai mentir pra você ou, no mínimo, vai te induzir ao erro.

E o parceiro, claro, também via um APM que *não mostrava nada suspeito*.

O pior dos mundos:  
**cada um com sua meia verdade e ninguém com a verdade completa.**

## “Ok, então vamos observar a camada do SO”

Essa é a reação natural. Mas aqui surge outro problema:

Como saber qual *socket* e qual porta o sistema operacional usou exatamente na requisição que o APM diz ter demorado 10 segundos?

Você não sabe.  
Seu monitoramento também não.  
E essa correlação fina entre APM → SO → Rede simplesmente **não existe**.

Não é descuido.  
É limitação técnica mesmo.

Monitoramos memórias, CPUs, discos, rede, GC, queries...  
Mas quando precisamos rastrear **uma única requisição** por todas as camadas?

A observabilidade moderna **não dá conta**.

E isso é aceitável na maioria dos casos, pois geralmente o problema é grande o suficiente para aparecer em todas as métricas ao mesmo tempo.

Mas quando temos **uma falha esporádica** no meio de **1 milhão** de requisições?

Aí começam os casos que podem levar **meses** para descobrir.  
E na maioria das vezes, são ignorados, pois não geram um impacto critico.

## Debug e Hands-on: indo para a lama

Voltamos à War Room.

O cliente abriu a VM → rodamos `tcpdump`.

Vimos algo mais ou menos assim e que já supeitavamos:

```bash
12:34:10.104512 IP 200.160.10.20.443 > 10.0.0.5.52144: Flags [S.], seq 987654321, ack 1234567891
12:34:10.410120 IP 200.160.10.20.443 > 10.0.0.5.52144: Flags [P.], seq 1:302, ack 517
12:34:10.411200 IP 200.160.10.20.443 > 10.0.0.5.52144: Flags [F.], seq 302, ack 518

12:34:11.022334 IP 200.160.10.20.443 > 10.0.0.5.52162: Flags [S.], seq 112233445, ack 765432101
12:34:11.260001 IP 200.160.10.20.443 > 10.0.0.5.52162: Flags [P.], seq 1:280, ack 498

12:34:11.909100 IP 200.160.10.20.443 > 10.0.0.5.52201: Flags [S.], seq 556677880, ack 443322111

```

Vamos entender esse exemplo de tcpdump:

```
12:34:10.104512 IP 200.160.10.20.443 > 10.0.0.5.52144: Flags [S.], seq 987654321, ack 1234567891

```

- `12:34:10.104512` → Timestamp
- `IP` → Indica que é um pacote IPv4 (o tcpdump mostraria "IP6" para IPv6).
- `200.160.10.20.443` → Indica que o servidor do parceiro está respondendo, Ou seja: **o servidor está enviando o pacote**.
- `>` → Direção do pacote, significa **para**.
- `10.0.0.5.52144` → Endereço de destino + porta efêmera que o sistema operacional abriu para receber a resposta.
- `Flags [S.]` → Flag do TCP para determinar o que significa o pacote

Perceba que o **endereço de destino + porta efêmera** muda constantemente, ou seja, muito provavelmente toda requisição abria um socket novo.

Rodamos `netstat`.

E a confirmação veio:

Mais de 1 mil sockets abertos, todos estavam em **TIME\_WAIT**.

Quando vemos TIME\_WAIT demais, significa:

- A aplicação **não está reutilizando conexões HTTP**
- Para cada chamada, ela abre um socket novo
- Portanto, refaz handshake TCP
- Portanto, paga latência extra
- Portanto, aumenta a chance de pegar um momento ruim na rede ou no parceiro

Isso explica tudo?

Não necessariamente.  
Mas **é um dos fatores que contribui** para uma lentidão intermitente.

Como resolver?

Simples (mas exige código):

- Ativar **HTTP keep-alive**
- Usar **Session / Connection Pool**
- Manter o socket em estado **ESTABLISHED**

Assim a aplicação reaproveita conexões, evita bursts de DNS, reduz handshakes e estabiliza a latência.

## Conclusão

No fim, parte do problema ainda pode estar do lado do parceiro.  
Mas entregamos algo que muitas consultorias não entregam:

- **Teoria clara**
- **Põe a teoria a prova** (tcpdump, netstat, análise de sockets)
- **Explicação das limitações de APM e observabilidade**
- **Evidências fortes para o cliente trabalhar com o parceiro**
- **Melhorias concretas para aplicar no próprio código**

O cliente entrou na War Room **convencido** de que o problema era do parceiro.  
Saiu dela **entendendo que parte da culpa também poderia ser dele** e que seu APM, sozinho, não podia ser tratado como verdade absoluta.

E, sinceramente?  
Para quem processa 1 milhão de requisições por dia, essa lição vale ouro.