· 6 min · API

El almacenamiento en caché de prompts, explicado: cuándo ahorra dinero y cuándo no

El almacenamiento en caché de prompts, explicado: cuándo ahorra dinero y cuándo no

A las 9:12 de la mañana de un lunes, uno de nuestros agentes de soporte empezó a costar 4x más de lo esperado.

El modelo no estaba alucinando, el gráfico de tráfico era correcto y nadie había cambiado accidentalmente de Haiku a Opus. El problema era más sencillo: cada solicitud incluía el mismo manual de políticas de 42,000 tokens, pero nuestra tasa de aciertos de la caché de prompts era prácticamente nula porque anteponíamos una marca de tiempo nueva y metadatos específicos del usuario al manual.

El mismo contenido. El mismo modelo. La misma aplicación. Ningún ahorro por caché.

La caché de prompts es una de esas funciones que parecen automáticas hasta que intentas reducir la factura. En la práctica, favorece una estructura de prompt muy concreta: un prefijo largo y estable que se reutiliza en muchas solicitudes. Si entiendes esa frase, normalmente puedes predecir si la caché ahorrará dinero o no tendrá ningún efecto sin que lo notes.

Qué almacena realmente la caché de prompts

La caché de prompts no es memoria semántica. El proveedor no está diciendo: «Esto se parece a algo que enviaste antes». Se acerca más a lo siguiente:

«El inicio de esta solicitud coincide lo suficiente con una secuencia de tokens anterior, para este modelo y esta política de caché, como para que podamos reutilizar el cómputo interno de ese prefijo».

Esa distinción importa.

La caché de prompts suele ser útil cuando envías repetidamente el mismo prefijo largo:

  • Instrucciones del sistema
  • Esquemas de herramientas
  • Conjuntos extensos de documentación
  • Catálogos de productos
  • Contexto del código fuente
  • Manuales legales o de políticas
  • Ejemplos de aprendizaje con pocos ejemplos
  • Resultados de recuperación estáticos reutilizados en muchas solicitudes

Normalmente no ayuda mucho cuando cada solicitud empieza de forma distinta:

  • Marcas de tiempo dinámicas al principio
  • Datos específicos del usuario antes del contenido compartido
  • Orden aleatorio de los ejemplos
  • UUID por solicitud dentro de la sección que se puede almacenar en caché
  • Fragmentos recuperados cuyo orden o formato cambia
  • Historial de chat colocado antes de las instrucciones estables

La decisión técnica fundamental es colocar primero el contexto estable y costoso, y después el contexto variable.

Anthropic frente a OpenAI: objetivo similar, controles distintos

Tanto Anthropic como OpenAI admiten la caché de prompts, pero la experiencia para el desarrollador es distinta.

Anthropic ofrece controles más explícitos para la caché de prompts. Puedes marcar bloques de contenido con controles de caché y luego consultar campos de uso como cache_creation_input_tokens y cache_read_input_tokens. Esto facilita entender si estás creando entradas de caché o leyendo de ellas.

La caché de prompts de OpenAI es más automática en los modelos compatibles. Cuando se reutiliza un prefijo de prompt, los tokens de entrada almacenados en caché pueden facturarse de forma distinta y aparecer en los metadatos de uso. Normalmente no defines puntos de corte explícitos de caché de la misma manera; en su lugar, estructuras las solicitudes para que el prefijo reutilizable sea estable a nivel de bytes y tokens.

La diferencia práctica está entre el control y la comodidad.

DimensiónCaché explícita al estilo de AnthropicCaché automática al estilo de OpenAI
Control del desarrolladorMayor; puedes marcar los bloques que se pueden almacenar en cachéMenor; el proveedor detecta los prefijos reutilizables
Facilidad de depuraciónNormalmente más clara gracias a los contadores de creación y lectura de cachéDepende de los metadatos de uso que exponga el modelo o la API
Importancia de la estructura del promptMuy altaMuy alta
Uso más adecuadoBloques estáticos grandes, herramientas, documentación y ejemplosPrefijos largos reutilizados en llamadas repetidas
Fallo habitualPunto de corte de caché colocado después del contenido dinámicoEl prefijo cambia antes de que la caché pueda encontrar una coincidencia
Modelo mental«Escribo y leo un prefijo con algo parecido a un nombre»«El proveedor reconoce este prefijo repetido»

Los detalles de implementación varían según el modelo y el proveedor, y siguen evolucionando. Pero la regla arquitectónica es estable: la caché se basa en prefijos repetidos, no en prompts similares.

El modelo de precios: creación frente a lectura

Una forma útil de entender la caché de prompts es dividir los tokens de entrada en tres categorías:

  1. Tokens de entrada normales: se facturan al precio habitual de entrada.
  2. Tokens de creación de caché: tokens utilizados para crear una entrada de caché, que suelen facturarse con un recargo o una tarifa especial de escritura.
  3. Tokens de lectura de caché: tokens leídos de una entrada de caché existente, que suelen facturarse a una tarifa reducida.

Anthropic expone esta distinción directamente mediante campos de uso como:

{
  "usage": {
    "input_tokens": 812,
    "cache_creation_input_tokens": 42000,
    "cache_read_input_tokens": 0,
    "output_tokens": 684
  }
}

En una solicitud posterior, si el prefijo encuentra una coincidencia en la caché, lo deseable es ver algo más parecido a esto:

{
  "usage": {
    "input_tokens": 936,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 42000,
    "output_tokens": 711
  }
}

La primera llamada crea la caché. Las llamadas posteriores leen de ella.

La rentabilidad depende de los precios actuales del proveedor, del tiempo de vida de la caché y del modelo. Como los precios cambian, prefiero modelar esto con variables en el código en lugar de fijar cifras en los documentos de diseño.

Esta es una pequeña función de Python que uso para decidir si merece la pena implementar la caché para una ruta:

def cache_savings(
    cached_tokens: int,
    normal_input_per_mtok: float,
    cache_write_per_mtok: float,
    cache_read_per_mtok: float,
    requests: int,
) -> dict:
    mtok = cached_tokens / 1_000_000

    no_cache = requests * mtok * normal_input_per_mtok
    with_cache = (
        mtok * cache_write_per_mtok +
        (requests - 1) * mtok * cache_read_per_mtok
    )

    return {
        "no_cache": round(no_cache, 6),
        "with_cache": round(with_cache, 6),
        "savings": round(no_cache - with_cache, 6),
        "savings_pct": round((1 - with_cache / no_cache) * 100, 2),
    }


print(cache_savings(
    cached_tokens=42_000,
    normal_input_per_mtok=3.00,
    cache_write_per_mtok=3.75,
    cache_read_per_mtok=0.30,
    requests=100,
))

Aquí solo se usan precios ilustrativos. Lo que importa es la estructura.

Con un prefijo reutilizable de 42,000 tokens y 100 solicitudes, la caché suele dar excelentes resultados. Con el mismo prefijo y una sola solicitud, la caché puede resultar más cara si el precio de escritura es superior al precio normal de entrada.

Esa es la primera gran salvedad: la caché de prompts se basa en la amortización. Si no reutilizas el prefijo almacenado en caché, no obtienes el beneficio.

La fórmula del punto de equilibrio

Puedes estimar el punto de equilibrio con:

no_cache_cost = N * T * normal_price

cache_cost = T * write_price + (N - 1) * T * read_price

Donde:

  • N es el número de solicitudes que usan el mismo prefijo
  • T es la cantidad de tokens que se pueden almacenar en caché
  • normal_price es el precio normal de los tokens de entrada
  • write_price es el precio de creación de caché
  • read_price es el precio de lectura de caché

La caché ahorra dinero cuando:

T * write_price + (N - 1) * T * read_price
  <
N * T * normal_price

El T se cancela al calcular el punto de equilibrio únicamente en términos de coste, lo que significa que la cantidad de reutilizaciones y los precios relativos determinan la decisión. Pero la cantidad de tokens sigue importando en términos operativos: ahorrar un 80 % sobre 500 tokens es insignificante; ahorrarlo sobre 80,000 tokens es una partida del presupuesto.

Una versión útil para un cálculo aproximado:

break_even_requests =
  (write_price - read_price) / (normal_price - read_price)

Si las escrituras de caché son solo un poco más caras que la entrada normal y las lecturas son mucho más baratas, el punto de equilibrio puede ser muy bajo. Si las escrituras de caché son caras o tu prefijo rara vez se repite, el ahorro de la caché es frágil.

Cómo estructurar los prompts para obtener prefijos estables

La mejor optimización de la caché de prompts no es un parámetro de la API. Es la disposición del prompt.

Disposición incorrecta:

Request ID: req_8f19a
Current time: 2026-02-14T09:12:33Z
User: customer_4812
Locale: en-US

SYSTEM INSTRUCTIONS:
...

POLICY MANUAL:
[42,000 tokens of stable text]

USER QUESTION:
Can I get a refund after 45 days?

Esto impide aprovechar la caché de prefijos porque el prompt cambia desde el principio.

Una disposición mejor:

SYSTEM INSTRUCTIONS:
...

POLICY MANUAL:
[42,000 tokens of stable text]

DYNAMIC REQUEST METADATA:
Request ID: req_8f19a
Current time: 2026-02-14T09:12:33Z
User: customer_4812
Locale: en-US

USER QUESTION:
Can I get a refund after 45 days?

El bloque estable va primero. El bloque dinámico va después.

Para la caché explícita al estilo de Anthropic, la estructura conceptual puede ser así:

{
  "model": "claude-sonnet-4-6",
  "max_tokens": 800,
  "system": [
    {
      "type": "text",
      "text": "You are a support policy assistant..."
    },
    {
      "type": "text",
      "text": "Refund policy manual v2026-02-01:\n\n...",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "Can I get a refund after 45 days?"
    }
  ]
}

El esquema exacto de la solicitud varía según la versión de la API y el SDK, así que considera esto una estructura orientativa, no código para copiar y pegar. Lo importante es que el bloque estable y extenso se marque explícitamente como apto para caché y no cambie entre llamadas.

Para la caché automática al estilo de OpenAI, la estructura del prompt importa igual de mucho, aunque no marques un bloque manualmente:

{
  "model": "gpt-5.5",
  "messages": [
    {
      "role": "system",
      "content": "You are a support policy assistant...\n\nRefund policy manual v2026-02-01:\n\n..."
    },
    {
      "role": "user",
      "content": "Can I get a refund after 45 days?"
    }
  ]
}

Si el mensaje de sistema cambia en cada solicitud, no deberías esperar lecturas de caché constantes.

Un patrón arquitectónico práctico

En los sistemas de producción, prefiero definir explícitamente en el código de la aplicación los prefijos de prompt almacenados en caché.

Un patrón sencillo:

prompt_prefix/
  support_policy_v17.txt
  tool_schema_v4.json
  examples_v9.md

runtime_request/
  user_question
  user_profile
  retrieved_recent_orders

Después, compón las solicitudes así:

from pathlib import Path

POLICY_PREFIX = Path("prompt_prefix/support_policy_v17.txt").read_text()
TOOL_SCHEMA = Path("prompt_prefix/tool_schema_v4.json").read_text()
EXAMPLES = Path("prompt_prefix/examples_v9.md").read_text()

def build_prompt(user_question: str, user_profile: dict) -> str:
    stable_prefix = f"""
You are a support policy assistant.

TOOLS:
{TOOL_SCHEMA}

POLICY:
{POLICY_PREFIX}

EXAMPLES:
{EXAMPLES}
""".strip()

    dynamic_suffix = f"""
USER PROFILE:
{user_profile}

USER QUESTION:
{user_question}
""".strip()

    return stable_prefix + "\n\n--- DYNAMIC REQUEST ---\n\n" + dynamic_suffix

En la práctica, también asigno una versión al prefijo. Si cambia el manual de políticas, quiero que eso sea un evento deliberado de invalidación de caché:

sha256sum prompt_prefix/support_policy_v17.txt

Ese hash se incluye en los registros junto al nombre del modelo, los tokens de creación de caché, los tokens de lectura de caché y la ruta de la solicitud. Sin esa observabilidad, los errores de caché son difíciles de diagnosticar porque la respuesta sigue funcionando; simplemente cuesta más.

Una línea de registro útil tiene este aspecto:

{
  "route": "support.answer",
  "model": "claude-sonnet-4-6",
  "prefix_hash": "9d3a4a...",
  "input_tokens": 932,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 42000,
  "output_tokens": 688,
  "latency_ms": 1840
}

No optimices basándote únicamente en la facturación. Registra el comportamiento de la caché por ruta.

Latencia: a menudo mejora, pero no hace magia

La caché de prompts puede reducir la latencia porque el proveedor del modelo puede reutilizar el cómputo del prefijo almacenado en caché. Pero no diseñaría un SLA suponiendo una reducción fija de la latencia sin haberla medido en mi propia carga de trabajo.

Lo que ocurre realmente en producción es más complejo:

  • Los prompts cortos pueden no mostrar ningún cambio significativo en la latencia.
  • Los prefijos largos almacenados en caché suelen mejorar el tiempo hasta el primer token.
  • La longitud de la salida sigue siendo el factor dominante en muchas solicitudes.
  • Las llamadas a herramientas, la latencia de red y las colas pueden ocultar los beneficios de la caché.
  • Los fallos de caché generan picos en la cola de la distribución de latencia si las escrituras son más lentas que las lecturas.

Una configuración realista para las pruebas de rendimiento es sencilla:

# warm cache
python run_eval.py --case support_refund --repeat 1

# measure cache reads
python run_eval.py --case support_refund --repeat 50 --jsonl out.jsonl

# inspect p50/p95 by cache_read_input_tokens > 0
python analyze_latency.py out.jsonl

Mide por separado las solicitudes con aciertos y fallos de caché. Mezclarlas te da una cifra que no explica ninguna de las dos.

Problemas habituales que veo en sistemas reales

1. Contenido dinámico antes del contenido estable

Este es el fallo más común. Una marca de tiempo, un ID de solicitud, un volcado de indicadores de funcionalidad, la configuración regional del usuario o la asignación a un experimento se coloca al principio del prompt del sistema.

Muévelo más abajo.

2. Un JSON «equivalente» no es equivalente

Estos dos fragmentos son semánticamente idénticos, pero no necesariamente idénticos a efectos de la caché:

{"name":"refund_lookup","timeout":3,"strict":true}
{
  "strict": true,
  "timeout": 3,
  "name": "refund_lookup"
}

Si incluyes esquemas de herramientas o configuración en el prefijo almacenado en caché, serialízalos de forma determinista:

import json

def stable_json(data: dict) -> str:
    return json.dumps(data, sort_keys=True, separators=(",", ":"))

Esto evita fallos de caché accidentales debidos a cambios en el orden de las claves o en los espacios en blanco.

3. La recuperación puede impedir el uso de la caché

Los sistemas RAG suelen construir prompts así:

Retrieved documents:
[doc A]
[doc B]
[doc C]

Instructions:
...

Si los resultados de recuperación cambian con cada consulta, el prefijo también cambia con cada consulta. Eso está bien si el contexto recuperado es realmente dinámico, pero no coloques tus instrucciones estables después de él.

Mejor:

Instructions:
...

Long-lived product documentation:
[stable docs]

Query-specific retrieved documents:
[doc A]
[doc B]
[doc C]

Para sistemas de gran volumen, considera dividir el contexto en:

  • Instrucciones estables a nivel global
  • Documentación estable por cliente
  • Recuperación específica del usuario o la consulta

Cada capa tiene un comportamiento de caché diferente.

4. Los TTL de la caché importan

Algunas entradas de caché caducan. Si tu tráfico llega en ráfagas, un prefijo puede reutilizarse intensamente durante diez minutos y luego dejar de usarse. Una mayor duración de la caché puede ayudar, pero los precios o la disponibilidad pueden variar según el proveedor y el modelo.

Aquí es donde importa la distribución de las solicitudes. «Recibimos 10,000 solicitudes al día» es menos útil que «recibimos 200 solicitudes por minuto para este prefijo exacto entre las 9 a. m. y las 10 a. m.».

5. Los cambios de modelo invalidan las suposiciones

No debes dar por hecho que un prefijo almacenado en caché para un modelo se puede reutilizar con otro. Si enrutas entre Claude Opus 4.8, Sonnet 4.6, GPT-5.5, Gemini 3 o modelos abiertos como Llama, Qwen, DeepSeek, MiniMax o Kimi, supervisa el comportamiento de la caché por modelo.

El enrutamiento entre varios modelos es útil, pero complica la amortización. Si el tráfico se reparte entre cinco modelos, cada uno puede recibir menos prefijos repetidos.

6. La personalización de prompts puede ser contraproducente

Los equipos suelen personalizar los prompts del sistema:

You are helping {{customer_name}}, who is on plan {{plan_name}}.

Eso parece inofensivo, pero si aparece antes del contenido almacenado en caché, cada cliente obtiene un prefijo distinto. Coloca la personalización más adelante, salvo que realmente cambie la interpretación del bloque estable por parte del modelo.

Cuándo el almacenamiento de prompts en caché ahorra dinero

El almacenamiento en caché suele ser muy adecuado cuando:

  • El prefijo que se puede almacenar en caché es grande, a menudo de miles o decenas de miles de tokens.
  • El mismo prefijo exacto se reutiliza muchas veces.
  • El prefijo se mantiene estable entre solicitudes.
  • El tráfico llega dentro del tiempo de vida de la caché.
  • Puedes observar los tokens de creación y lectura de caché.
  • La ruta tiene una composición de prompts predecible.

Ejemplos concretos:

  • Un asistente de programación incluye repetidamente el mismo mapa del repositorio y la misma guía de estilo.
  • Un bot de soporte incluye el mismo manual de políticas en cada pregunta sobre reembolsos.
  • Un agente utiliza un esquema de herramientas estático y grande en cada solicitud.
  • Un asistente interno de investigación incluye la misma descripción general del corpus para un equipo.

Para estas cargas de trabajo, el almacenamiento de prompts en caché puede ser una de las optimizaciones de costes con mayor impacto porque no requiere reducir la calidad del contexto. Conservas el prompt largo; simplemente dejas de pagar el precio completo de entrada cada vez.

Cuándo el almacenamiento de prompts en caché no ayuda

El almacenamiento en caché aporta poco o resulta perjudicial cuando:

  • El prompt es corto.
  • Los prefijos rara vez se reutilizan.
  • La mayor parte del contexto procede de una recuperación específica de la consulta.
  • Los datos dinámicos aparecen antes de los datos estables.
  • Modificas constantemente las instrucciones durante los experimentos.
  • El tráfico está muy disperso entre muchos modelos, clientes o variantes de prompts.
  • Las escrituras de caché cuestan más y las lecturas son demasiado infrecuentes para amortizarlas.

Un problema habitual durante la evaluación: el almacenamiento de prompts en caché parece poco eficaz en un notebook porque ejecutas cada caso una sola vez. Luego parece excelente en producción porque miles de usuarios comparten el mismo prefijo estable. También ocurre lo contrario: una demostración repite el mismo prompt 100 veces y muestra un gran ahorro, pero en producción hay personalizaciones por cliente que impiden reutilizarlo.

Haz pruebas con la distribución real de las solicitudes.

Una lista sencilla para comprobar si estás preparado para usar la caché

Antes de habilitar el almacenamiento de prompts en caché o depender de él, compruebo lo siguiente:

  • ¿Hay al menos un prefijo estable de más de unos pocos miles de tokens?
  • ¿Aparece antes de todo el contenido dinámico?
  • ¿La serialización es determinista?
  • ¿El prefijo tiene una versión y un hash?
  • ¿Puedo registrar los tokens de creación y lectura de caché?
  • ¿Conozco el número previsto de reutilizaciones durante el tiempo de vida de la caché?
  • ¿He medido la latencia por separado para los aciertos y los fallos de caché?

Si la respuesta a tres o más preguntas es «no», el almacenamiento en caché puede seguir funcionando, pero estás haciendo conjeturas.

Conclusiones prácticas

El almacenamiento de prompts en caché no es una compresión mágica. Es la reutilización de un prefijo estable de tokens, y la ventaja económica proviene de pagar un coste de creación una vez y un coste de lectura menor muchas veces.

El procedimiento de ingeniería es sencillo:

  • Coloca primero el contenido estable de gran tamaño: instrucciones, herramientas, documentación y ejemplos.
  • Mueve las marcas de tiempo, los metadatos del usuario, los resultados de recuperación y los ID de solicitud después del prefijo que se puede almacenar en caché.
  • Registra cache_creation frente a cache_read tokens por ruta y modelo.
  • Usa una serialización determinista para los esquemas de herramientas y la configuración en JSON.
  • Calcula el punto de equilibrio con los precios reales de tu proveedor y tu distribución de tráfico.
  • Ten cuidado con el enrutamiento entre varios modelos, la personalización por cliente y los prompts cortos.
  • Mide la latencia de los aciertos y los fallos por separado en lugar de confiar en los promedios.

La mejor optimización de caché de prompts que he visto no tuvo nada de ingenioso: movimos 42,000 tokens estables antes de 12 tokens dinámicos. El comportamiento del modelo no cambió. La factura sí.

A

AI Prime Tech publica este blog. Los artículos se redactan con asistencia de IA; comprueba los detalles específicos de cada versión, como los identificadores de modelos, los precios y los límites, en la documentación oficial antes de basarte en ellos.

Obtén acceso más económico a la API de Claude

Una sola clave de API para Claude Opus 5.5, Sonnet 5, Haiku 4.5 y Fable 5.1, además de GPT-6 modelos. Pago por uso, sin suscripción.

Obtén tu clave de API →
AI Prime Tech es una pasarela de API independiente de terceros. Claude™ y Anthropic® son marcas comerciales de Anthropic, PBC. No se implica ninguna afiliación ni respaldo.