🟣 Buenas prácticas avanzadas
Ya entiendes el caché y qué lo rompe. Ahora viene la pauta para el día a día: cuándo el caché resuelve y cuándo compactar resuelve cómo diseñar el prefijo para nunca invalidar sin querer, y un kit de prompts listos para ejecutarlo hoy en Claude Code.
Leyenda: caché baja el eje vertical (precio por token, ÷10) pero no cambia el ancho; compactar se mueve en el eje horizontal (cantidad de tokens, ÷20). Son ejes diferentes — quieres ambos.
Lo que dominarás al final de este recorrido
La caché ya no es un misterio para ti. Lo que falta es decidir bien: la caché abarata el precio por token, pero no reduce cuántos tokens que cargas — y el límite de contexto (1M) se refiere a la cantidad. Esta ruta te enseña a leer ambos ejes y a armar el prefijo para que nunca invalidar por accidente, y entrega prompts listos para auditar y corregir la caché directamente en Claude Code.
Caché vs. compactación
Dos ejes diferentes. Cuándo un contexto cacheado sigue siendo caro y cuándo 1 write en frío de compactación se amortiza.
Arquitectura favorable al caché
System congelado, tools determinísticas, fork que reutiliza el prefijo del padre, checklist de invalidadores silenciosos y precalentamiento.
Prompts listos
6 prompts copiables: auditar la caché, ordenar tools, decidir si compactar, diagnosticar cache_read=0, revisar el system y planificar breakpoints.
Mapa de la ruta
⚖️ Caché vs. compactación
Dos ejes, un límite
🏛️ Arquitectura y auditoría
Congela el prefijo
📋 Prompts listos
Copia, pega y ejecuta
Contenido detallado
⚖️ Caché vs. compactación
La caché optimiza el precio por token; compactar optimiza cuántos tokens cargas. Son ejes diferentes, y solo la compactación resuelve el límite de contexto.
La caché optimiza el precio por token del contexto. Compactar (resumir el historial en una versión más corta; en Claude Code, /compact) optimiza cuántos tokens que cargas.
Sin separar los ejes, piensas que el caché «lo resuelve todo» e ignoras el límite de contexto, o compactas demasiado pronto y pierdes el caché caliente.
No compiten en el mismo eje; quieres ambos; la decisión es cuándo aplicar cada uno.
La caché reduce el costo por token, pero leer 400k tokens a 0,1× todavía equivale a ~40k de input lleno por turno, cada turno.
El descuento engaña: un contexto enorme y barato por token sigue siendo pesado en total.
0,1× de mucho sigue siendo mucho; el volumen importa incluso con un hit alto.
La caché hace que 900k tokens sean baratos, pero aun así ocupan 900k de 1M. En algún momento no puedes continuar sin compactar o /clear.
El límite se refiere a la cantidad; solo compactar/limpiar libera espacio.
Barato ≠ pequeño; el límite es de cantidad, no de precio.
Sin compactar: 400k @0,1× ≈ 40k-equiv por turno, para siempre. Al compactar a 20k: 1 write frío 20k @1,25× ≈ 25k (una vez), después 20k @0,1× ≈ 2k-equiv por turno.
Payback en ~1 turno; cada turno siguiente cuesta ~20× menos.
Cambia un costo único por turnos mucho más baratos.
Un contexto inflado dispersa la atención del modelo ("context rot") y, aunque se lea desde el caché, 400k tardan más en generar el primer token (TTFT mayor) que 20k.
Compactar mejora la precisión y la velocidad, no solo el costo.
Menos tokens = más enfoque + respuesta más rápida.
Conversación pequeña → NO compactes (solo pierdes el caché caliente sin obtener ningún beneficio). Contexto grande, cerca del límite o con la calidad en descenso → compacta.
La intuición de que «compactar siempre ahorra» es falsa en una conversación corta.
Cambia 1 write frío único por turnos más ligeros — solo vale la pena cuando hay suficientes turnos por delante.
🏛️ Arquitectura pro caché y auditoría
Diseña el prefijo para que nunca se invalide por accidente: system congelado, tools determinísticas, fork que copia el prefijo del padre, checklist y precalentamiento.
No interpolar la fecha/hora, el modo ni el nombre del usuario en el system: queda antes del prefijo e invalida todo. Inyecta el contexto dinámico después, en las messages.
Una variable en el system hace que todo el cache de tools + system se descarte en cada turno.
System estable = prefijo estable; lo dinámico va al final.
Serializa la lista de tools siempre en el mismo orden (ordena por nombre). Set/dict sin sort = orden variable = miss.
Las tools quedan en la posición 0; un orden inestable invalida todo silenciosamente.
Mismo orden = mismos bytes = hit.
La caché es por modelo. Cambiar de modelo invalida todo. ¿Necesitas un modelo más barato para una subtarea? Usa un subagente y mantén el ciclo principal en un solo modelo.
Cambiar el modelo «solo para esta» reinicia todo el prefijo.
Un modelo por loop; delega las variaciones a subagentes.
Una operación lateral (resumen, subagente) que reconstruye system/tools/model diferente pierde la caché del padre. Copia system/tools/model verbatim y agrega lo específico al final.
Un fork bien hecho hereda el cache caliente y solo guarda el bloque nuevo.
Prefijo idéntico al del padre + sufijo específico al final.
Revisa lo que alimenta el prefijo: datetime.now(), uuid, json.dumps sin sort_keys, set, tools por usuario, secciones condicionales en el system.
Son los culpables de cache_read_input_tokens siempre 0.
Prefijo determinístico byte a byte.
Solicitud max_tokens: 0 al iniciar la app guarda la caché del prefijo y responde de inmediato. TTL 1h (write ~2×) para tráfico con gaps > 5 min.
Solo sirve si la latencia inicial es visible, el prefijo es grande y hay un momento antes del tráfico.
Calienta el caché antes del primer usuario; 1h para pausas largas.
📋 Prompts listos (copy-run)
Seis prompts reales que puedes copiar: cada uno con un objetivo, un bloque copiable (con las partes que debes cambiar) y una forma de verificar el resultado en Claude Code.
Prompt que le pide a Claude Code revisar el código que construye el prompt y enumerar cada silent invalidator + su solución.
Convierte «mi caché no coincide» en una lista de acciones.
Objetivo + bloque listo para copiar + cómo verificar.
Prompt que pide ordenar la serialización de tools por nombre y confirma que el orden sea estable entre requests.
Elimina la principal fuente de misses silenciosos en la posición 0.
Serialización estable = prefijo idéntico.
Prompt que estima el costo por turno de cargar el contexto actual frente al costo único de compactarlo, y recomienda qué hacer.
Saca la decisión de las suposiciones y ponle números.
Costo por turno vs. un único write frío.
Prompt que compara los bytes del prefijo entre dos requests iguales y señala el byte que cambia.
cache_read_input_tokens siempre 0 = hay un invalidador; el diff lo detecta.
Dos requests, un diff, el byte culpable.
Prompt que quita la interpolación dinámica del system y la mueve al final de los mensajes.
Congela el system sin perder el contexto dinámico.
Estable al principio, dinámico al final.
Prompt que sugiere dónde colocar cache_control (final del system estable; final del fragmento compartido en un prefijo+sufijo variable) y alerta sobre el 20-block lookback.
Con pocos breakpoints, en los lugares correctos, se obtiene más.
Máx. 4 breakpoints; cuidado con el lookback de 20 bloques.