DevGuideTK
← Trilha Backend

DNS

Como um nome de domínio vira um endereço IP, quem responde em cada etapa e por que uma mudança de DNS demora a valer para todos.

A maior parte do trabalho com DNS no backend é investigação e configuração de cliente. Você raramente escreve um resolvedor. O que precisa saber é consultar, ler a resposta e entender o que a sua linguagem faz com ela.

Consultar com o dig

O dig mostra a resposta do DNS sem nenhuma camada no meio. A forma curta devolve só o valor:

dig +short api.loja.com.br A

A forma completa mostra o TTL restante, na segunda coluna da resposta:

dig api.loja.com.br A
;; ANSWER SECTION:
api.loja.com.br.    187    IN    A    203.0.113.10

O número 187 indica que o resolvedor consultado ainda vai usar essa resposta por 187 segundos. Rodar o comando de novo mostra o número diminuindo, o que prova que a resposta veio do cache.

Três variações resolvem a maior parte das investigações:

# Perguntar a um resolvedor específico, para comparar caches
dig @1.1.1.1 api.loja.com.br A
dig @8.8.8.8 api.loja.com.br A

# Perguntar direto ao servidor autoritativo, sem cache nenhum
dig +short NS loja.com.br
dig @ns1.provedor-exemplo.net api.loja.com.br A

# Refazer o caminho completo a partir da raiz
dig +trace api.loja.com.br

Resolver um nome pelo código

Os exemplos resolvem os endereços de um nome usando a biblioteca padrão.

import { resolve4 } from "node:dns/promises";

const enderecos = await resolve4("example.com", { ttl: true });

for (const { address, ttl } of enderecos) {
  console.log(`${address} (TTL ${ttl}s)`);
}

O que muda de uma linguagem para outra

As cinco chamadas parecem iguais e se comportam de formas diferentes por baixo.

Quem resolveCache dentro do programaPonto de atenção
Nodedns.lookup, usado pelo fetch e pelo http, chama o sistema operacional. dns.resolve*, do exemplo, fala direto com o servidor DNSNenhumdns.lookup ocupa uma thread do pool interno, que tem 4 por padrão. Um DNS lento atrasa também leitura de arquivos e criptografia
PythonO sistema operacional, por getaddrinfoNenhumA chamada bloqueia. No asyncio, ela é executada em uma thread separada
GoUm resolvedor próprio, escrito em Go, que lê a configuração do sistema no LinuxNenhumAceita context, então o tempo limite cobre a resolução
JavaO sistema operacional, pela JVMSim: 30 segundos para respostas positivas por padrãoConfigurações antigas ou com gerenciador de segurança guardam a resposta para sempre
C#O sistema operacionalNenhum na resoluçãoO HttpClient mantém conexões abertas sem limite de idade por padrão

No Node, as duas famílias de função podem dar respostas diferentes para o mesmo nome. dns.lookup respeita o arquivo hosts da máquina e dns.resolve4 o ignora. Isso explica o caso de um nome que funciona no fetch e falha no script de diagnóstico.

O problema real: conexões que duram mais que o DNS

Nenhuma das cinco linguagens guarda o DNS por muito tempo. O endereço antigo sobrevive por outro motivo: o cliente HTTP reaproveita conexões. Enquanto uma conexão estiver aberta, ninguém consulta o DNS de novo, e o programa continua falando com o endereço resolvido horas ou dias antes.

O sintoma clássico é este: o serviço de destino muda de endereço em um deploy ou failover, as instâncias recém-iniciadas funcionam e as que estavam no ar há mais tempo continuam chamando o endereço antigo.

A correção é limitar a idade das conexões, para forçar uma nova resolução de tempos em tempos.

// .NET: recicla as conexões a cada 2 minutos, o que força nova consulta DNS
var handler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(2),
};
var cliente = new HttpClient(handler);
// Java: define o cache de DNS da JVM em 30 segundos, antes da primeira resolução
java.security.Security.setProperty("networkaddress.cache.ttl", "30");
// Go: fecha as conexões ociosas depois de 90 segundos
transporte := &http.Transport{IdleConnTimeout: 90 * time.Second}
cliente := &http.Client{Transport: transporte, Timeout: 5 * time.Second}
LinguagemO que configurar
NodeO tempo de vida das conexões ociosas no agente HTTP da biblioteca em uso
PythonOs limites e a expiração do pool da biblioteca (requests, httpx)
GoIdleConnTimeout no http.Transport. Conexões em uso constante não são fechadas por ele
Javanetworkaddress.cache.ttl e o tempo de vida das conexões do cliente HTTP
C#PooledConnectionLifetime no SocketsHttpHandler

Lista de revisão

Use esta lista ao revisar código que chama outros serviços ou ao planejar uma mudança de DNS:

No código

  • O tempo limite da chamada cobre a resolução do nome, e não só a conexão e a resposta?
  • O cliente HTTP tem um limite de idade para as conexões reaproveitadas?
  • O pool de conexões do banco tem tempo máximo de vida configurado?
  • Em Java, o valor de networkaddress.cache.ttl é conhecido e adequado?
  • Uma falha de resolução é registrada no log como erro de DNS, distinta de erro de conexão?

Na operação

  • O TTL foi reduzido com antecedência maior que o TTL antigo antes da migração?
  • O servidor antigo continua no ar até os caches vencerem?
  • A alteração foi conferida no servidor autoritativo com o dig?
  • Os registros estão versionados, com histórico de quem alterou?

Prompts para aprofundar

Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.

  • Investigar um problema de DNS com o dig

    Quero treinar o diagnóstico de problemas de DNS pela linha de comando.
    
    Primeiro, ensine a ler a saída completa do comando dig: as seções de pergunta, resposta e autoridade, o TTL, os indicadores do cabeçalho e o código de status (NOERROR, NXDOMAIN, SERVFAIL). Explique também as opções +short, +trace e a consulta a um servidor específico com @.
    
    Depois simule quatro incidentes, um de cada vez. Em cada um, descreva só o sintoma, deixe que eu diga quais comandos rodaria, mostre a saída que cada comando daria e peça a minha conclusão antes de revelar a causa:
    1. "Alterei o registro há duas horas e ainda vejo o endereço antigo."
    2. "O site abre na minha máquina e não abre para um cliente."
    3. "O nome não resolve de jeito nenhum, e o registro existe no painel."
    4. "O serviço resolve dentro do container, mas com um endereço diferente do que aparece fora dele."
    
    A cada passo, diga se o comando que escolhi ajuda ou não, e por quê. No final, monte um roteiro de diagnóstico com a ordem de verificação que eu deveria seguir.
  • Cache de DNS e conexões na minha linguagem

    Quero entender como a minha linguagem e as minhas bibliotecas tratam a resolução de DNS, para evitar que a aplicação fique presa a um endereço antigo.
    
    Pergunte qual linguagem, qual versão, qual biblioteca de cliente HTTP e qual biblioteca de acesso a banco de dados eu uso.
    
    Depois explique, especificamente para esse conjunto:
    1. Quem faz a resolução do nome (o sistema operacional ou a própria linguagem) e se existe cache dentro do processo, com o valor padrão.
    2. Como o reaproveitamento de conexões do cliente HTTP faz o endereço antigo sobreviver, mesmo sem cache de DNS.
    3. Quais opções de configuração controlam o tempo de vida das conexões no cliente HTTP e no pool do banco de dados, com exemplo de código.
    4. Se o tempo limite que eu configuro nas chamadas cobre a etapa de resolução do nome.
    
    Em seguida, descreva o cenário de um failover de banco de dados em que o nome passa a apontar para outro servidor, e pergunte o que acontece com a minha aplicação nas configurações padrão. Corrija o meu raciocínio e mostre a configuração recomendada.
    
    Sempre que citar um valor padrão, diga de qual versão ele vale e recomende que eu confirme na documentação oficial.
  • Revisar o uso de DNS no meu código

    Vou colar abaixo um trecho de código ou de configuração que chama outros serviços pela rede: cliente HTTP, pool de banco de dados, configuração de container ou de orquestrador. Revise com foco em resolução de nomes e conexões de longa duração.
    
    Verifique, nesta ordem, e para cada item diga se está correto, incorreto ou ausente:
    1. Os destinos são referenciados por nome ou por endereço IP fixo? Há endereços fixos que deveriam ser nomes?
    2. O cliente HTTP é reaproveitado? Existe limite de idade para as conexões abertas?
    3. O pool de conexões do banco tem tempo máximo de vida e validação antes do uso?
    4. Os tempos limite cobrem a resolução do nome, a conexão e a resposta?
    5. Uma falha de resolução é tratada e registrada de forma que eu consiga distingui-la de outros erros de rede?
    6. Há novas tentativas quando a resolução falha? Com qual intervalo?
    
    Para cada problema, explique o incidente de produção que ele pode causar e mostre a correção. Não reescreva o que já está correto.
    
    Código ou configuração:
    [cole aqui]