304 Not Modified: por que é um sucesso, não um erro
304 Not Modified é um sucesso: significa que a sua cópia em cache do recurso ainda está atual, então o servidor não está enviando corpo nenhum e está dizendo para você reutilizar o que já tem. Ele só aparece em resposta a uma requisição condicional, e é por isso que uma verificação de monitoramento que não envia cabeçalhos de cache nunca vai ver um.
Como um 304 acontece
Um 304 é a segunda metade de uma conversa em duas etapas. Na primeira requisição, o servidor devolve o recurso com um validador: um ETag, que é um identificador opaco para aquela versão exata, e muitas vezes uma data de Last-Modified. O cliente guarda a resposta junto com esses validadores.
Mais tarde, quando a cópia em cache precisa ser revalidada, o cliente repete a requisição e inclui o que tem:
If-None-Match: "abc123"carrega o ETag guardado. Esse é o validador preferido porque é exato.If-Modified-Since: Wed, 03 Sep 2026 10:00:00 GMTcarrega a data guardada, usada quando não há um ETag.
Se o recurso não mudou, o servidor responde 304 Not Modified só com cabeçalhos e sem corpo, e o cliente renderiza a sua cópia em cache. Se mudou, o servidor responde 200 com o conteúdo novo e novos validadores. Os dois resultados são comportamento correto.
Por que um 304 é uma boa notícia, não um erro
As pessoas veem 304 em um painel de rede do navegador ou em um analisador de logs, notam que não é um 200, e presumem que algo falhou. Nada falhou. Um 304 é a resposta útil mais barata da web: nenhum corpo de resposta atravessa a rede, então a transferência é de algumas centenas de bytes em vez do recurso inteiro, e o servidor geralmente evita regenerar o recurso, então custa menos CPU do que um 200 custaria. A página renderiza mais rápido porque o navegador reutiliza bytes que já tem. Os rastreadores também se beneficiam, já que um ETag estável que produz 304s permite que um buscador gaste o orçamento de rastreamento dele em páginas que mudaram.
Uma proporção alta de 304s em recursos estáticos é um sinal de que o cache está bem configurado. A única coisa a observar é se você precisa da ida e volta de revalidação de qualquer forma: para recursos versionados ou com fingerprint, um Cache-Control: max-age longo com immutable evita até o 304, porque o navegador nem pergunta.
Quando um 304 é um problema
- Uma página desatualizada que não atualiza. Se o seu HTML é servido com um validador que nunca muda enquanto o conteúdo muda, os navegadores continuam recebendo 304 e os usuários continuam vendo a página antiga. Esse é o bug clássico do "eu implantei mas ninguém vê".
- Um 304 sem cópia em cache correspondente. Se um cliente envia uma requisição condicional sem ter motivo para isso, ou um proxy remove o corpo de um 200, o cliente fica sem nada para renderizar e a página aparece em branco.
- ETags fracos ou instáveis atrás de um balanceador de carga. Quando vários backends geram ETags diferentes para o conteúdo idêntico, toda revalidação erra e você recebe 200s completos onde 304s eram esperados. O tráfego sobe sem motivo.
- Compressão mudando o validador. Se o ETag difere entre as variantes comprimida e não comprimida sem um
Vary: Accept-Encodingcorreto, os caches podem servir a coisa errada.
Como testar requisições condicionais
- Busque o recurso e leia os validadores dele:
curl -sI https://example.com/style.css | grep -Ei "^(HTTP|etag|last-modified|cache-control)" - Repita a requisição com o ETag que você recebeu e confirme que o servidor responde 304:
Substitua pelo valor exato do ETag, aspas incluídas. Um 200 aqui significa que a revalidação não está funcionando.curl -sI -H 'If-None-Match: "abc123"' https://example.com/style.css | head -n 1 - Se você receber 200 quando esperava 304, verifique se um proxy ou CDN está removendo o
If-None-Match, e se os seus backends concordam sobre o ETag do mesmo arquivo. - Se você receber uma página desatualizada, faça o validador mudar quando o conteúdo mudar. Nomes de arquivo com fingerprint são a correção mais confiável; senão, derive o ETag do próprio conteúdo.
- Mantenha o HTML com um tempo de vida de frescor curto e deixe os recursos carregarem o longo. HTML que fica em cache por um dia é o que torna uma implantação invisível.
Por que verificações de uptime nunca veem um 304
Uma verificação de uptime solicita uma página como um visitante de primeira vez, sem If-None-Match e sem If-Modified-Since, então o servidor não tem nada para comparar e sempre responde 200. Esse é o padrão certo para disponibilidade. Também significa que regressões de cache não aparecem nos dados de uptime de jeito nenhum: um site pode servir a todo mundo uma página desatualizada enquanto toda verificação continua verde. Faça asserções sobre o conteúdo da página além do status, e uma página que parou de atualizar se torna visível como uma incompatibilidade de conteúdo. A HostTracker oferece 13 tipos de monitor e monitora sites desde 2004. Teste cabeçalhos e status com a ferramenta de verificação HTTP, e veja o que um 200 OK realmente prova e o guia completo da família 3xx.