¿Odias los anuncios? Ir Sin publicidad Hoy

Encabezados de caché HTTP Control de caché, ETag y max-age sin adivinar

Actualizado en

Una guía práctica de los encabezados de caché HTTP para desarrolladores web: qué hacen realmente las directivas Cache-Control, cómo los ETags desencadenan la revalidación 304, cómo elegir tiempos de vida (TTL) que sobrevivan las implementaciones y los errores que hacen que la caché perjudique en lugar de ayudar.

Encabezados de caché HTTP: Cache-Control, ETag y max-age Sin Adivinar 1
ANUNCIO · ¿ELIMINAR?

Cada respuesta HTTP que envíes se almacena en caché o no — y si no actúas deliberadamente, el navegador decide por ti. El resultado suele ser una mezcla de caché agresivo para cosas que cambian frecuentemente y sin caché para cosas que cambian raramente. Ambos perjudican a tus usuarios.

Este guía te da el modelo mental para configurar correctamente los encabezados de caché HTTP por primera vez: qué controla cada directiva, cómo los ETags desencadenan la revalidación y cómo elegir tiempos de vida (TTL) que sobrevivan a las actualizaciones sin servir contenido obsoleto.

Cómo funciona realmente el caché del navegador

Cuando el navegador solicita un recurso, primero revisa su caché local. Si existe una copia reciente en caché, la sirve inmediatamente — sin ninguna solicitud de red. Si la copia en caché podría estar obsoleta, envía una solicitud condicional al origen. El origen responde con un 304 No Modificado si el recurso no ha cambiado o envía la respuesta actualizada completa (200 OK).

Los CDNs se sitúan en el medio de este ciclo de vida. Almacenan respuestas más cerca de los usuarios geográficamente y obedecen los mismos encabezados de caché HTTP — con algunas extensiones específicas de CDN como s-maxage.

Tres preguntas determinan el comportamiento de caché:

  • ¿Este recurso es cachable en absoluto? Controlado por Cache-Control: no-store o private
  • ¿Durante cuánto tiempo es fresco? Controlado por max-age o s-maxage
  • ¿Cómo se valida la obsolescencia? Controlado por ETags o Last-Modified

directivas del encabezado Cache-Control

El Cache-Control el encabezado es la forma principal de declarar la política de caché. Varias directivas están separadas por comas. Aquí está lo que cada una hace realmente:

max-age

max-age=N indica a los cachés (navegador y CDN) cuántos segundos permanece la respuesta fresca. Una respuesta con max-age=86400 se considera fresca durante exactamente 24 horas desde que fue recibida. Después de ese tiempo, el caché debe revalidar antes de servirla de nuevo.

Para activos estáticos con nombres de archivo versionados (como main.abc123.js), un año completo es común: max-age=31536000. Para documentos HTML, una ventana mucho más corta — o ninguna caché en absoluto — es más segura, ya que los documentos HTML hacen referencia a esos activos versionados.

s-maxage

s-maxage sobrescribe max-age solo para cachés compartidos (CDNs, servidores proxy). El navegador la ignora. Esto permite servir respuestas largamente almacenadas a los usuarios mientras mantiene el borde del CDN más fresco. Un patrón típico es Cache-Control: public, max-age=3600, s-maxage=86400 — el navegador almacena durante 1 hora, el CDN durante 24 horas.

no-cache

no-cache no significa "no cachear". Significa que el caché debe revalidar con el origen antes de servir la respuesta almacenada, incluso si aún está fresca. La respuesta se almacena, pero cada uso requiere un viaje de red para verificar que aún es válida. Esto es adecuado para contenido que cambia frecuentemente pero que beneficia de ahorro de ancho de banda mediante una respuesta 304.

no-store

no-store es la única directiva que realmente previene el caché. Ningún caché del navegador, ningún caché del CDN, ninguna escritura en disco. Usa esta directiva para respuestas que contienen datos sensibles de los usuarios — estados bancarios, registros médicos, tokens. No la uses como valor predeterminado porque aún no has pensado en el caché.

public y private

public permite explícitamente que los cachés compartidos (CDNs) almacenen la respuesta, incluso cuando la solicitud tenía un Authorization encabezado. private limita el caché solo al navegador del usuario final — los CDNs no deben almacenarla. Para respuestas autenticadas que son específicas del usuario, private previene que una respuesta de un usuario sea servida a otro.

must-revalidate

must-revalidate impide que los cachés sirvan respuestas obsoletas cuando no pueden alcanzar al origen. Sin esta directiva, un caché podría servir una respuesta expirada si la red no está disponible. Con ella, la solicitud falla con un 504 si el origen no está alcanzable. Usa esta directiva para contenido en el que servir datos obsoletos es peor que un error.

ETags: revalidación precisa

Un ETag es un identificador generado por el servidor para una versión específica de un recurso — piensa en ello como un "dedo de huella" para el cuerpo de la respuesta. El servidor lo envía en la respuesta:

ETag: "abc123def456"

Cuando la copia en caché expira, el navegador envía una solicitud condicional con el ETag almacenado:

If-None-Match: "abc123def456"

Si el recurso no ha cambiado, el servidor responde con 304 Not Modified y un cuerpo vacío — ahorrando ancho de banda mientras confirma la frescura. Si ha cambiado, el servidor responde con 200 OK y el nuevo ETag.

ETags fuertes vs débiles

A ETag fuerte ("abc123") significa que la respuesta es idéntica byte a byte. Un ETag débil (W/"abc123") significa que las respuestas son semanticamente equivalentes pero pueden diferir en detalles triviales como espacios en blanco o orden de encabezados. Los ETags débiles se pueden generar de forma más eficiente, pero no se pueden usar en solicitudes de rango. A menos que tengas una razón específica para usar ETags débiles, usa los fuertes.

Last-Modified: la alternativa más antigua

Antes de los ETags, los servidores usaban Last-Modified marcadores de tiempo para la revalidación. El servidor envía:

Last-Modified: Thu, 01 May 2026 12:00:00 GMT

El navegador revalida con:

If-Modified-Since: Thu, 01 May 2026 12:00:00 GMT

El servidor devuelve 304 si el recurso no ha cambiado desde ese marcador de tiempo.

La debilidad: los marcadores de tiempo tienen una precisión de un segundo. Un archivo modificado dos veces en el mismo segundo aparecerá como no modificado. Los ETags manejan esto correctamente y son preferidos. La mayoría de los marcos modernos envían ambos — el navegador utiliza cualquiera que esté disponible, con los ETags teniendo prioridad.

Romper el caché sin romper las actualizaciones

Un largo max-age en un activo estático solo es seguro si el URL cambia cuando el contenido cambia. Dos estrategias existen:

Fingerprinting del URL (recomendado)

Incluye un hash del contenido del archivo en el nombre del archivo: main.a1b2c3d4.js. Cuando el archivo cambia, el hash cambia, el URL cambia y el navegador descarga el nuevo archivo — evitando completamente el caché. La antigua URL permanece en el caché pero ya no se solicita nuevamente una vez que el HTML hace referencia al nuevo URL.

Webpack, Vite y la mayoría de los bundlers modernos lo hacen automáticamente. Este patrón te permite establecer Cache-Control: public, max-age=31536000, immutable — la immutable directiva indica al navegador que no se preocupar por revalidar incluso si la entrada en caché es técnicamente obsoleta.

Cadenas de consulta (menos confiables)

Añadiendo una versión al URL como cadena de consulta (main.js?v=1.2.3) técnicamente crea una URL diferente, pero algunos CDNs y proxies ignoran las cadenas de consulta al construir las claves de caché. El fingerprinting del URL en la ruta es más confiable y universalmente soportado.

Errores comunes que perjudican el caché

Cachear respuestas de API que no deberían ser cacheadas

APIs en formato JSON que devuelven datos específicos del usuario o sensibles al tiempo deben usar Cache-Control: no-store o al menos private, no-cache. Un error común es permitir que un CDN almacene una respuesta como /api/user/profile y servir los datos de un usuario a otro. Si tu API no establece un Cache-Control encabezado, algunos CDNs lo almacenan de todos modos usando heurísticas.

Olvidar Vary: Accept-Encoding

Si tu servidor sirve versiones comprimidas y no comprimidas de un recurso según el encabezado del cliente Accept-Encoding , el caché debe almacenar copias separadas para cada variante. Sin Vary: Accept-Encoding, un CDN podría almacenar la versión comprimida y servirla a un cliente que no soporta gzip — o al revés. Siempre establece este encabezado cuando la compresión es condicional.

Usar no-cache cuando se quiere evitar el caché por completo

Los desarrolladores a menudo escriben Cache-Control: no-cache cuando quieren evitar completamente el caché, pero no-cache almacena la respuesta — solo requiere revalidación antes de cada uso. Usa no-store cuando realmente no quieras que la respuesta se almacene en ningún lugar.

Establecer max-age en HTML sin una estrategia de caché que rompa

Los documentos HTML hacen referencia a activos versionados. Si cachear tu HTML con un largo max-age, los usuarios no recibirán los nuevos nombres de archivo tras una actualización — seguirán ejecutando el HTML antiguo, que hace referencia a los hashes antiguos. Establece un TTL corto (o no-cache) en HTML y reserva los TTL largos para los activos inmutables que referencia HTML.

Calcula tu ventana de expiración antes de lanzar

Elegir un valor de max-age es más fácil cuando puedes visualizar qué significa en tiempo real. El Calculadora de TTL de caché HTTP / max-age de iotools.cloud te permite introducir un TTL en segundos y ver la fecha exacta de expiración. Útil para verificar valores como 86400 (24 horas), 2592000 (30 días) o 31536000 (1 año) antes de comprometerlos en tu configuración del servidor o en las reglas del CDN.

Una lista práctica de políticas de caché

  • Documentos HTML: Cache-Control: no-cache — siempre revalida, beneficia de 304s cuando nada cambia
  • Activos estáticos versionados (JS, CSS, imágenes con hash en el nombre del archivo): Cache-Control: public, max-age=31536000, immutable
  • Activos estáticos no versionados (fuentes, favicon): Cache-Control: public, max-age=604800 (1 semana)
  • Respuestas de API (públicas, sensibles al tiempo): Cache-Control: public, max-age=60, s-maxage=300 — TTL corto en el navegador, TTL más largo en el CDN
  • Respuestas de API (específicas del usuario): Cache-Control: private, no-cache
  • Datos sensibles: Cache-Control: no-store
  • Siempre establece Vary: Accept-Encoding al servir respuestas comprimidas condicionalmente

Los ETags deben estar activos por defecto para cualquier cosa que estés almacenando — son la mecanismo que hace que la revalidación sea eficiente en ancho de banda. La mayoría de los servidores web (Nginx, Apache, Caddy) generan ETags automáticamente a menos que los hayas desactivado.

¿Quieres eliminar publicidad? Adiós publicidad hoy

Instalar extensiones

Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas

añadir Extensión de Chrome añadir Extensión de borde añadir Extensión de Firefox añadir Extensión de Opera

¡El marcador ha llegado!

Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!

ANUNCIO · ¿ELIMINAR?
ANUNCIO · ¿ELIMINAR?
ANUNCIO · ¿ELIMINAR?

Noticias Aspectos técnicos clave

Involucrarse

Ayúdanos a seguir brindando valiosas herramientas gratuitas

Invítame a un café
ANUNCIO · ¿ELIMINAR?