Cache web: guia completo de HTTP, Service Worker e build

Cache web: guia completo de HTTP, Service Worker e build

Já perdi a conta de quantas vezes ouvi “limpa a cache que resolve” de clientes, colegas e até de gente que se diz técnica. Segundo o Sapo.pt, a prática pode deixar o dispositivo mais lento, não mais rápido. Depois de anos debugando problemas de performance em produção, posso confirmar: quem limpa cache indiscriminadamente está, na maioria dos casos, sabotando o próprio sistema.

Por que a cache existe (e por que apagá-la é quase sempre um erro)

Cache é um trade-off clássico da engenharia: gastamos disco ou memória RAM para economizar tempo de CPU e latência de rede. É um dos poucos casos onde você literalmente “compra velocidade” com espaço. No meu fluxo diário, percebo que desenvolvedores que entendem isso otimizam o sistema de forma cirúrgica. Quem não entende, fica no “reset total” toda vez que algo trava.

A lógica é simples: quando você acessa um site ou abre um app, o sistema guarda pedaços reutilizáveis — imagens, scripts, tokens de autenticação, dados de sessão, respostas de API. Na próxima vez, ele não precisa buscar tudo de novo. Apagar essa informação obriga o sistema a reaprender o que já sabia. É como um aluno que deleta todas as anotações antes da prova e depois precisa assistir a aula inteira outra vez.

A própria Google já alertou que limpar a cache do Chrome e do Android pode tornar a abertura de páginas visivelmente mais demorada. Isso não é opinião, é métrica medida por quem mantém o navegador mais usado do planeta.

Como a cache funciona no nível técnico

Quem programa precisa enxergar isso em camadas. Não é tudo a mesma coisa.

Cache HTTP: o pão com manteiga de qualquer aplicação web

Quando você faz uma requisição, o servidor responde com cabeçalhos como Cache-Control, ETag e Last-Modified. Esses cabeçalhos dizem ao browser (e a proxies intermediários) por quanto tempo aquele recurso pode ser reutilizado sem nova requisição. Exemplo real que vejo em todo projeto sério:

HTTP/1.1 200 OK
Content-Type: application/javascript
Cache-Control: public, max-age=31536000, immutable
ETag: "abc123"
Content-Length: 45230

Esse immutable é ouro. Diz ao browser: “esse arquivo nunca vai mudar, nem se preocupe em validar de novo”. Frameworks como Next.js, Vite e Webpack já geram hashes no nome do arquivo (app.a1b2c3.js) justamente para permitir esse tipo de cache agressiva sem quebrar versões.

Service Workers: cache programável no front-end

Aqui é onde a coisa fica interessante para quem trabalha com PWA. O Service Worker intercepta requisições e permite estratégias como cache-first, network-first, stale-while-revalidate. Apagar a cache de um SW bem configurado pode literalmente quebrar a aplicação offline.

// Estratégia stale-while-revalidate para assets estáticos
self.addEventListener('fetch', (event) => {
  if (event.request.destination === 'image' ||
      event.request.destination === 'script' ||
      event.request.destination === 'style') {
    event.respondWith(
      caches.open('assets-v1').then(cache => {
        return cache.match(event.request).then(cachedResponse => {
          const fetchPromise = fetch(event.request).then(networkResponse => {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          });
          return cachedResponse || fetchPromise;
        });
      })
    );
  }
});

Esse padrão é o que faz apps como Twitter Lite e Starbucks carregarem em menos de 2 segundos em conexões 3G. Quando o usuário limpa a cache do browser, esse SW é desinstalado silenciosamente. Resultado: primeira visita lenta de novo até o SW ser reinstalado.

Cache de aplicação: Redux, React Query, Vuex

Quem usa React Query ou SWR sabe que a cache em memória evita requests duplicadas e mantém a UI responsiva. Apagar esse estado (via DevTools, por exemplo) força refetches que travam a interface por alguns segundos. Já vi gente debugar “bug de lentidão” que era simplesmente DevTools aberto limpando estado a cada reload.

Cache de build: Webpack, Vite, Docker

Ferramentas modernas dependem desesperadamente de cache para serem usáveis. O node_modules/.cache do Webpack, o .vite do Vite, o ~/.docker/buildx do Docker — tudo isso existe para evitar reprocessar o que já foi processado. Limpar essas pastas “para resolver problema” é receita para esperar 15 minutos numa build que normalmente leva 40 segundos.

Na Prática: quando limpar cache faz sentido (e como fazer direito)

Não vou dizer que cache nunca deve ser limpa. Há cenários legítimos. A questão é saber diferenciar.

  1. Bug específico em um recurso: uma imagem quebrada, um CSS desatualizado que mostra layout errado após deploy. Nesse caso, hard refresh (Ctrl+Shift+R) resolve sem afetar o resto.
  2. Disco cheio: se o dispositivo está com 0 bytes livres, faz sentido limpar caches grandes e não essenciais. Use ferramentas que mostram o tamanho por app — no Android, vá em Configurações → Apps → [app específico] → Armazenamento. Não faça “limpeza geral”.
  3. Desenvolvimento local: quando você muda headers de cache no servidor e quer testar imediatamente. Aí sim, limpa o cache do browser específico daquele domínio.
  4. Cache corrompido confirmado: crash consistente logo após abrir um app, com logs apontando para dados corrompidos. Aí vale limpar aquele app específico.

O ponto-chave é: limpeza seletiva, nunca geral. Quem usa Linux/Mac pode ir além com comandos precisos:

# Limpa apenas cache de um projeto específico (Webpack)
rm -rf node_modules/.cache

# Invalida cache do Docker para uma imagem específica
docker builder prune --filter "label=stage=builder"

# Limpa cache de pip sem tocar em pacotes instalados
pip cache purge

# Limpa apenas cache de testes do Jest em um projeto
npx jest --clearCache

Cada comando resolve um problema específico sem efeitos colaterais no resto do sistema.

Erros comuns que devs cometem com cache

Na minha experiência revisando código e atendendo emergências, esses são os deslizes mais frequentes.

  • Chamar window.location.reload(true) em produção achando que “vai limpar a cache dos usuários”. Não vai. Isso só força reload do client que executou. O cache dos outros clientes segue intacto e desatualizado. Solução: deploy com versionamento de assets (cache busting por hash).
  • Definir Cache-Control: no-store em respostas que poderiam ser cacheadas. Já vi APIs inteiras com isso porque alguém teve preguiça de pensar em invalidação. Resultado: backend bombardo com requests desnecessárias, latência alta, custo de infraestrutura inflado.
  • Não versionar a chave de cache no Service Worker. Quando você atualiza a estratégia de cache, os usuários ficam presos na versão antiga até limpar manualmente. Padrão correto: incrementar o nome do cache (assets-v1assets-v2) e deletar o antigo no evento activate.
  • Limpar cache de produção como “passo de deploy”. Vira gargalo e downtime. Cache existe para ser persistente. Invalidação deve ser cirúrgica.
  • Não medir antes de “otimizar”. Antes de sair limpando ou reconfigurando, rode Lighthouse, WebPageTest ou Chrome DevTools Performance tab. Otimização sem métrica é chute.
  • Confundir cache de DNS com cache de browser. Trocar DNS ou ter problema de propagação não se resolve limpando cache de browser. São sistemas independentes.

Cache também é observabilidade

Um ponto que poucos discutem: cache bem configurada funciona como termômetro. Hit rate acima de 90% para assets estáticos é saudável. Abaixo de 60%, tem algo errado na estratégia. Quem usa Redis ou Memcached precisa monitorar keyspace_hits vs keyspace_misses. Cache que ninguém acerta é cache inútil e memória desperdiçada.

Em produção, já resolvi incidentes olhando exatamente para os gráficos de cache miss. Spikes repentinos geralmente indicam deploy mal feito, mudança de hash de asset não propagada ou CDN com problema regional.

FAQ — perguntas que todo dev já fez

Limpar cache do celular com app “Cleaner” realmente acelera?

Na maioria dos casos, não. Esses apps limpam cache de tudo indiscriminadamente, causando exatamente o efeito oposto descrito no Sapo.pt. Alguns ainda rodam em segundo plano consumindo RAM e bateria, piorando o cenário. O Android moderno já gerencia cache automaticamente — apps que não usa há semanas têm a cache podada pelo sistema.

Como forçar atualização de cache em produção sem afetar todos os usuários?

Use versionamento de assets (filename hashing) combinado com Cache-Control: max-age longo para os arquivos versionados e max-age=0 apenas para o index.html. Assim, deployar nova versão obriga o browser a buscar o HTML novo, que aponta para os novos hashes de JS/CSS, que vêm com cache fresca.

Service Worker cache vs HTTP cache: qual prevalece?

O Service Worker intercepta antes da cache HTTP do browser. Se o seu SW responder com algo do Cache Storage, a HTTP cache nem entra na jogada. Por isso caches no SW devem ser explicitamente gerenciadas — esquecimento de limpeza vira bug fantasma que aparece semanas depois.

Vale a pena usar Redis para cache de API?

Depende da taxa de leitura vs escrita e do custo de regenerar a resposta. Para endpoints com leitura intensa e dados que mudam pouco (catálogo de produtos, sessões de usuário, rate limiting), Redis paga o investimento em poucos dias. Para dados que mudam a cada segundo, cache vira fonte de inconsistência e dor de cabeça.

Limpar cache pode causar perda de dados?

Cache não é armazenamento persistente, então tecnicamente não. Mas em apps mal desenhados que guardam estado do usuário na cache (em vez de em banco), sim — limpar pode deslogar, perder carrinho de compra ou progresso não salvo. Se o app faz isso, o bug é do app, não da cache em si.

No fim das contas, cache é uma das ferramentas mais subestimadas do desenvolvimento web moderno. Entender como ela funciona em cada camada separa quem escreve software performático de quem fica apagando cache toda sexta-feira “porque sexta dá bug”. Se você chegou até aqui, já está no primeiro grupo.

Gostou? Me segue no GitHub e deixa um comentário se tiver dúvida ou quiser aprofundar algum ponto.

Y

Yuri Sousa

Front-End Developer / Designer

Desenvolvedor apaixonado por criar experiências digitais acessíveis e visualmente perfeitas. Escrevo sobre desenvolvimento web, design e tecnologia.