🟣 Boas práticas avançadas
Você já entende o cache e o que o quebra. Agora vem a régua do dia a dia: quando o cache resolve e quando compactar resolve, como desenhar o prefixo para nunca invalidar sem querer, e um kit de prompts prontos pra rodar no Claude Code hoje.
Legenda: cache desce o eixo vertical (preço por token, ÷10) mas não mexe na largura; compactar anda no eixo horizontal (quantidade de tokens, ÷20). São eixos diferentes — você quer os dois.
O que você domina ao fim desta trilha
O cache já não é mistério pra você. O que falta é decidir bem: o cache barateia o preço por token, mas não reduz quantos tokens você carrega — e o teto de contexto (1M) é sobre quantidade. Esta trilha ensina a ler os dois eixos, a montar o prefixo pra ele nunca invalidar por acidente, e entrega prompts prontos pra auditar e corrigir cache direto no Claude Code.
Cache vs compactação
Dois eixos diferentes. Quando um contexto cacheado ainda sai caro, e quando 1 write frio de compactação paga por si.
Arquitetura pró-cache
System congelado, tools determinísticas, fork que reusa o prefixo do pai, checklist de silent invalidators e pré-aquecimento.
Prompts prontos
6 prompts copiáveis: auditar cache, ordenar tools, decidir compactar, diagnosticar cache_read=0, revisar system e planejar breakpoints.
Mapa da trilha
⚖️ Cache vs Compactação
Dois eixos, um teto
🏛️ Arquitetura e auditoria
Congela o prefixo
📋 Prompts prontos
Copia, cola, roda
Conteúdo detalhado
⚖️ Cache vs Compactação
Cache otimiza o preço por token; compactar otimiza quantos tokens você carrega. Eixos diferentes — e o teto de contexto só a compactação resolve.
Cache otimiza o preço por token do contexto. Compactar (resumir o histórico numa versão menor; no Claude Code, /compact) otimiza quantos tokens você carrega.
Sem separar os eixos, você acha que cache "resolve tudo" e ignora o teto de contexto — ou compacta cedo demais e perde o cache quente.
Não competem no mesmo eixo; você quer os dois; a decisão é quando aplicar cada um.
Cache barateia por token, mas 400k tokens lidos a 0,1× ainda equivalem a ~40k de input cheio por turno, todo turno.
O desconto engana: um contexto enorme e barato por token continua pesado no total.
0,1× de muito ainda é muito; o volume importa mesmo com hit alto.
O cache deixa 900k tokens baratos, mas eles ainda ocupam 900k de 1M. Uma hora você não continua sem compactar ou /clear.
O teto é sobre quantidade; só compactar/limpar libera espaço.
Barato ≠ pequeno; o limite é de quantidade, não de preço.
Sem compactar: 400k @0,1× ≈ 40k-equiv por turno, pra sempre. Compactando pra 20k: 1 write frio 20k @1,25× ≈ 25k (uma vez), depois 20k @0,1× ≈ 2k-equiv por turno.
Payback em ~1 turno; cada turno seguinte fica ~20× mais leve.
Troca um custo único por turnos muito mais baratos.
Contexto inchado espalha a atenção do modelo ("context rot") e, mesmo lido do cache, 400k levam mais tempo pro 1º token (TTFT maior) que 20k.
Compactar melhora precisão e velocidade, não só custo.
Menos tokens = mais foco + resposta mais rápida.
Conversa pequena → NÃO compacte (só perde o cache quente sem ganho). Contexto grande, perto do teto ou com qualidade caindo → compacte.
A intuição "compactar sempre economiza" é falsa em conversa curta.
Troca 1 write frio único por turnos mais leves — só vale quando há turnos suficientes à frente.
🏛️ Arquitetura pró-cache e auditoria
Desenhe o prefixo pra ele nunca invalidar sem querer: system congelado, tools determinísticas, fork que copia o prefixo do pai, checklist e pré-aquecimento.
Não interpolar data/hora, modo ou nome do usuário no system — fica na frente do prefixo e invalida tudo. Injete contexto dinâmico depois, nas messages.
Uma variável no system derruba o cache de tools + system todo turno.
System estável = prefixo estável; dinâmico vai pro fim.
Serialize a lista de tools sempre na mesma ordem (ordene por nome). Set/dict sem sort = ordem variável = miss.
As tools ficam na posição 0; ordem instável invalida tudo silenciosamente.
Mesma ordem = mesmos bytes = hit.
Cache é por modelo. Trocar de modelo invalida tudo. Precisa de um modelo mais barato pra subtarefa? Use subagente, mantendo o loop principal num modelo só.
Trocar modelo "só nessa" reinicia o prefixo inteiro.
Um modelo por loop; delegue a variação a subagentes.
Operação lateral (resumo, subagente) que remonta system/tools/model diferente perde o cache do pai. Copie system/tools/model verbatim e anexe o específico no fim.
Um fork bem feito herda o cache quente e só grava o bloco novo.
Prefixo idêntico ao do pai + sufixo específico no fim.
Varra o que alimenta o prefixo: datetime.now(), uuid, json.dumps sem sort_keys, set, tools por usuário, seções condicionais no system.
São os culpados de cache_read_input_tokens sempre 0.
Prefixo determinístico byte a byte.
Requisição max_tokens: 0 ao subir o app grava o cache do prefixo e retorna na hora. TTL 1h (write ~2×) pra tráfego com gaps > 5 min.
Só vale se a 1ª latência é visível, o prefixo é grande e há um momento antes do tráfego.
Aquece o cache antes do 1º usuário; 1h pra pausas longas.
📋 Prompts prontos (copy-run)
Seis prompts coláveis reais: cada um com objetivo, bloco copiável (com as partes que você troca) e como verificar o resultado no Claude Code.
Prompt que manda o Claude Code varrer o código que monta o prompt e listar cada silent invalidator + o fix.
Transforma "meu cache não bate" numa lista acionável.
Objetivo + bloco colável + como verificar.
Prompt que pede ordenar a serialização de tools por nome e confirmar ordem estável entre requests.
Elimina a fonte #1 de miss silencioso na posição 0.
Serialização estável = prefixo idêntico.
Prompt que estima o custo por turno de carregar o contexto atual vs o custo único de compactar, e recomenda.
Tira a decisão do achismo e põe números.
Custo por turno vs write frio único.
Prompt que faz diff dos bytes do prefixo entre dois requests iguais e aponta o byte que muda.
cache_read_input_tokens sempre 0 = tem invalidator; o diff acha.
Dois requests, um diff, o byte culpado.
Prompt que tira interpolação dinâmica do system e move pro fim das messages.
Congela o system sem perder o contexto dinâmico.
Estável no começo, dinâmico no fim.
Prompt que sugere onde colocar cache_control (fim do system estável; fim do trecho compartilhado num prefixo+sufixo variável) e alerta sobre o 20-block lookback.
Poucos breakpoints, nos lugares certos, rendem mais.
Máx. 4 breakpoints; cuidado com o lookback de 20 blocos.