Estratégias de cache com Claude Code para apps reais
Guia prático de cache HTTP, CDN, Service Worker, Redis e invalidação usando Claude Code.
Cache não é um botão mágico para deixar uma aplicação rápida. Em um produto real, headers HTTP, CDN, Service Worker, Redis e memória do processo armazenam dados diferentes por tempos diferentes. Se você pedir ao Claude Code apenas “adicione cache”, a aplicação pode parecer mais rápida, mas ainda mostrar preço antigo, estoque errado ou dados privados para a pessoa errada.
Este guia traz uma estratégia prática para entregar ao Claude Code antes da edição de código. Masa testou estes padrões em uma pequena aplicação Express e em um fluxo de site de conteúdo; o maior ganho veio de decidir qual camada é dona de cada dado antes de adicionar Redis ou Service Worker.
flowchart LR
User[Browser] --> Http[HTTP cache]
Http --> SW[Service worker Cache API]
SW --> CDN[CDN or edge cache]
CDN --> App[Node or app server]
App --> Redis[Redis or app cache]
App --> DB[(Database)]
Comece pelas decisões
Antes de Claude Code implementar, responda a quatro perguntas:
- Quais usuários podem ver a mesma resposta?
- Quanto tempo o dado pode ficar desatualizado sem causar problema?
- Qual key, URL ou tag de cache será removida depois de uma atualização?
- Quem executa rollback ou purge quando o cache está errado?
Imagens, CSS e bundles JavaScript com hash costumam poder viver muito tempo. Páginas de cobrança, configurações de conta e HTML autenticado não devem entrar em cache compartilhado. O guia da MDN sobre HTTP caching explica a diferença entre cache privado do navegador e cache compartilhado, como proxy ou CDN.
Comparação das camadas
| Camada | Melhor uso | TTL sugerido | Invalidação | Falha comum |
|---|---|---|---|---|
| Cache HTTP do navegador | Imagens, CSS, JS, API pública curta | 1 minuto a 1 ano | Nome do arquivo, ETag, Cache-Control | API longa demais mostra tela antiga |
| CDN ou edge | Lista de produtos, HTML de artigo, OGP | 30 segundos a 1 dia | Purge por URL, tag ou deploy | HTML autenticado fica compartilhado |
| Service Worker Cache API | Página offline, app shell, JSON estável | Por versão | Mudar nome no release | Worker antigo serve bundle antigo |
| Redis ou cache da app | Agregados DB, APIs externas, rankings | 10 segundos a 1 hora | Design de keys, eventos, TTL | KEYS bloqueia Redis em produção |
| Memória do processo | Configuração, feature flags curtos | Segundos a minutos | Reinício ou clear explícito | Instâncias divergem |
Coloque esta tabela em CLAUDE.md para que Claude Code tenha uma regra estável ao adicionar rotas. Para instruções de projeto, veja CLAUDE.md best practices.
Caso 1: cache HTTP no Express
O primeiro cache a corrigir geralmente não é Redis, mas o header da resposta. Cache-Control diz a navegadores e CDNs por quanto tempo uma resposta pode ser armazenada. A MDN documenta as diretivas em Cache-Control header.
Copie como server.js e execute.
npm install express
node server.js
// server.js
const express = require("express");
const app = express();
function cacheControl(req, res, next) {
const path = req.path;
if (path.startsWith("/assets/")) {
res.set("Cache-Control", "public, max-age=31536000, immutable");
return next();
}
if (path.startsWith("/api/private/")) {
res.set("Cache-Control", "no-store");
return next();
}
if (path.startsWith("/api/public/")) {
res.set("Cache-Control", "public, max-age=60, s-maxage=300, stale-while-revalidate=600");
res.set("Vary", "Accept-Encoding");
return next();
}
res.set("Cache-Control", "no-cache");
next();
}
app.use(cacheControl);
app.use("/assets", express.static("public/assets"));
app.get("/api/public/products", (_req, res) => {
res.json({ items: ["book", "template", "consultation"], generatedAt: new Date().toISOString() });
});
app.get("/api/private/me", (_req, res) => {
res.json({ userId: "demo-user", plan: "team" });
});
app.listen(3000, () => {
console.log("http://localhost:3000");
});
A decisão importante é separar rotas públicas e privadas. /api/private/ recebe no-store, então navegador e CDN não devem armazenar. APIs públicas usam TTL curto no navegador e TTL um pouco maior no CDN com s-maxage.
No prompt para Claude Code, escreva a regra: respostas autenticadas devem usar no-store; somente APIs públicas podem usar s-maxage.
Caso 2: helper getOrSet com Redis
Redis é útil para reduzir consultas repetidas ao banco ou a APIs externas. O padrão seguro é cache-aside: consultar Redis primeiro, buscar na fonte em caso de miss e salvar com TTL.
npm install redis
// cache.js
const { createClient } = require("redis");
const redis = createClient({
url: process.env.REDIS_URL || "redis://localhost:6379",
});
let connecting;
async function client() {
if (redis.isOpen) return redis;
if (!connecting) connecting = redis.connect();
await connecting;
return redis;
}
async function getOrSet(key, ttlSeconds, loader) {
const r = await client();
const cached = await r.get(key);
if (cached !== null) {
return JSON.parse(cached);
}
const fresh = await loader();
await r.set(key, JSON.stringify(fresh), { EX: ttlSeconds });
return fresh;
}
async function invalidate(keys) {
const r = await client();
if (keys.length > 0) {
await r.del(keys);
}
}
module.exports = { getOrSet, invalidate };
// products.js
const { getOrSet, invalidate } = require("./cache");
async function loadProductsFromDb() {
return [
{ id: "p1", name: "Prompt Templates", price: 500 },
{ id: "p2", name: "Claude Code Consultation", price: 15000 },
];
}
async function getPublicProducts() {
return getOrSet("products:list:v1", 300, loadProductsFromDb);
}
async function updateProduct(productId, patch) {
console.log("update db", productId, patch);
await invalidate(["products:list:v1", `products:item:${productId}:v1`]);
}
module.exports = { getPublicProducts, updateProduct };
Evite KEYS products:* em produção. Com muitos keys, isso pode bloquear Redis. Prefira listas de keys conhecidas, sets de keys relacionadas ou um comando de manutenção baseado em SCAN.
Caso 3: versionamento com Service Worker Cache API
Um Service Worker pode interceptar requisições do navegador. A Cache API é útil para página offline, app shell e assets estáticos. O risco é servir código antigo: se o nome do cache não muda, um worker velho pode continuar entregando JavaScript antigo depois do deploy.
// public/sw.js
const CACHE_VERSION = "claude-code-cache-v2026-06-01";
const STATIC_CACHE = `${CACHE_VERSION}:static`;
const PRECACHE_URLS = ["/", "/offline.html", "/assets/app.css"];
self.addEventListener("install", (event) => {
event.waitUntil(
caches
.open(STATIC_CACHE)
.then((cache) => cache.addAll(PRECACHE_URLS))
.then(() => self.skipWaiting())
);
});
self.addEventListener("activate", (event) => {
event.waitUntil(
caches
.keys()
.then((names) =>
Promise.all(
names
.filter((name) => !name.startsWith(CACHE_VERSION))
.map((name) => caches.delete(name))
)
)
.then(() => self.clients.claim())
);
});
self.addEventListener("fetch", (event) => {
const request = event.request;
if (request.method !== "GET") return;
event.respondWith(
caches.match(request).then((cached) => {
if (cached) return cached;
return fetch(request)
.then((response) => {
if (response.ok && new URL(request.url).pathname.startsWith("/assets/")) {
const copy = response.clone();
caches.open(STATIC_CACHE).then((cache) => cache.put(request, copy));
}
return response;
})
.catch(() => caches.match("/offline.html"));
})
);
});
Registre no ponto de entrada do cliente.
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("/sw.js");
});
}
Diga ao Claude Code que o nome do cache deve incluir data de release ou build ID, e que caches antigos devem ser apagados em activate.
Caso 4: prompt de auditoria para Claude Code
Claude Code é mais útil quando audita o repositório inteiro, não apenas quando adiciona um helper. Os Claude Code common workflows recomendam ciclos pequenos de investigação, edição e verificação, o que combina bem com cache.
Você é responsável por auditar o comportamento de cache em uma aplicação web.
Inspecione este repositório procurando headers HTTP, pressupostos de CDN, Service Worker, Redis e caches em memória de processo.
Retorne:
1. Dados armazenados por cada camada
2. TTL e condição de invalidação
3. Risco de respostas pessoais ou autenticadas chegarem a cache compartilhado
4. Telas concretas onde stale data pode aparecer
5. Plano mínimo de correção e comandos de verificação
Restrições:
- Marque suposições claramente
- Siga os padrões existentes do projeto
- Sugira refactors grandes separadamente, sem aplicar de imediato
Esse prompt funciona como cache de contexto reutilizável. Em vez de explicar a política toda vez, guarde a checklist em um template ou em CLAUDE.md e passe apenas o diff atual.
Cenários práticos
Em um catálogo de produtos ou loja de templates, cards públicos podem ficar pouco tempo no CDN e a lista do banco pode ficar cinco minutos no Redis. Ao editar um produto, remova a key da lista e faça purge da URL afetada no CDN.
Em um dashboard administrativo, receita, page views e conversões podem ser cacheados por 30 segundos a 5 minutos. Permissões, notificações pessoais e cobrança devem ser private ou no-store.
Em docs e blogs, o HTML do artigo pode ficar pouco tempo no edge, assets com hash podem durar bastante, e a shell offline pode ser gerenciada pelo Service Worker. É adequado para sites com muito conteúdo como ClaudeCodeLab.
Em APIs externas, Redis ajuda a absorver rate limits de clima, câmbio, planos SaaS ou feeds de status. Peça ao Claude Code para verificar os termos oficiais, pois alguns provedores limitam armazenamento.
Armadilhas
O erro mais grave é cachear HTML autenticado no CDN. Se a resposta depende de cookies, use private ou no-store por padrão. Se precisar da velocidade do CDN, separe a shell pública dos dados específicos do usuário.
A falta de Vary também gera respostas erradas. Se idioma, compressão, dispositivo ou autorização mudam a resposta, separe a URL ou envie o Vary correto.
Redis pode sofrer cache stampede quando uma key popular expira e muitas requisições chegam ao banco ao mesmo tempo. Use jitter no TTL, lock curto ou fallback no estilo stale-while-revalidate.
Service Worker pode manter arquivos removidos vivos. Versione o cache, apague nomes antigos em activate e mantenha um procedimento emergencial para unregister.
Runbook de invalidação
- Defina o escopo: produto, artigo, usuário ou app inteiro.
- Termine a escrita no banco primeiro; se falhar, não apague cache.
- Remova Redis com keys conhecidas, sets relacionados ou
SCAN. - Faça purge do CDN por URL ou tag. Purge total é último recurso.
- Aumente a versão do cache do Service Worker e confirme que os antigos sumiram.
- Verifique com
curl -I, DevTools e logs de hit rate do Redis. - Em incidente, reduza TTL ou mova rotas sensíveis para
no-store, depois restaure aos poucos.
Inclua este runbook na definição de pronto do Claude Code. Para disciplina de equipe, combine com Claude Code productivity tips.
Treinamento, templates e consultoria
Se você quer transformar isso em workflow repetível para a equipe, comece pela biblioteca de produtos e templates da ClaudeCodeLab para alinhar CLAUDE.md, prompts de review e prompts de auditoria. Se o desafio é mapear CDN, Redis, permissões e regras de revisão em um repositório real, use a página de treinamento e consultoria Claude Code.
Como referências oficiais, consulte a MDN sobre HTTP caching, a Cache API, Cache-Control e os Claude Code common workflows.
Depois de testar os exemplos deste artigo, Masa viu menos requisições repetidas de assets estáticos, respostas públicas mais previsíveis com TTLs orientados a CDN e leituras desnecessárias do banco mais visíveis com getOrSet. O Service Worker mostrou a principal lição: sem remoção versionada, CSS antigo sobrevive ao deploy. O ganho prático não é só velocidade; é registrar onde cada valor pode envelhecer.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Permission receipt no Claude Code: escopo, prova e rollback
Padrão de permission receipt para Claude Code: ações permitidas, limites de aprovação, comandos de prova, rollback e CTA de receita.
Agent Harness seguro para Claude Code e Codex: permissoes, verificacao e rollback
Monte uma base segura para agentes com Claude Code e Codex usando politicas, plano, verificacao e recuperacao.
Subagentes no Claude Code: guia prático para delegar trabalho com segurança
Guia prático de subagentes no Claude Code para dividir artigos e código: regras, prompts, riscos e checklist.