La cabecera Cache-Control es la instrucción HTTP que le dice a navegadores, CDNs y proxies intermedios cómo deben almacenar y cuánto tiempo pueden reutilizar un recurso antes de volver a pedirlo al servidor. Configurarla bien puede reducir el tiempo de carga en visitas repetidas a casi cero para recursos estáticos.
En este artículo aprenderás qué directivas existen, cómo elegir la correcta para cada tipo de recurso y cómo aplicarla en Apache, Nginx o directamente desde PHP.
Qué Es Cache-Control y Por Qué Importa
Cuando un navegador visita tu sitio por primera vez descarga todos los recursos: HTML, CSS, JavaScript, imágenes, fuentes. Sin caché, en la segunda visita vuelve a descargarlos todos. Con una política de caché correcta, solo descarga los que cambiaron.
Cache-Control reemplazó cabeceras más antiguas como Expires y Pragma: no-cache. Es la forma moderna y precisa de controlar el comportamiento de caché en HTTP/1.1 y versiones posteriores.
Una mala política de caché tiene dos caras: un tiempo de caché muy corto desperdicia ancho de banda y ralentiza el sitio; un tiempo muy largo hace que los usuarios vean versiones desactualizadas de CSS o JavaScript después de un deploy. El truco está en la estrategia.
Directivas Principales de Cache-Control
La cabecera acepta una o más directivas separadas por comas. Estas son las más relevantes:
| Directiva | Efecto |
|---|---|
max-age=N |
El recurso es válido durante N segundos desde que fue descargado. |
s-maxage=N |
Como max-age pero solo para cachés compartidas (CDN, proxy). |
no-cache |
Guarda en caché pero revalida con el servidor antes de servir. |
no-store |
No almacena el recurso en ningún tipo de caché. |
public |
Permite que CDNs y proxies compartan la respuesta entre usuarios. |
private |
Solo el navegador del usuario puede almacenar la respuesta (no CDNs). |
immutable |
El recurso nunca cambiará; el navegador no revalida durante max-age. |
stale-while-revalidate=N |
Sirve el recurso en caché mientras lo actualiza en segundo plano. |
La combinación más común para activos estáticos con fingerprinting
Cache-Control: public, max-age=31536000, immutable
Un año de caché (max-age=31536000) más immutable le dice al navegador que nunca revalide. Esto funciona siempre que el nombre del archivo incluya un hash de contenido (fingerprinting): app.a3f2c1.js. Al hacer deploy, el hash cambia, la URL cambia y el navegador descarga la nueva versión.
Para HTML y respuestas dinámicas
Cache-Control: no-cache
no-cache no significa "no guardes en caché" — eso es no-store. no-cache significa "guarda en caché pero revalida antes de servir". El navegador envía una petición condicional (If-None-Match o If-Modified-Since) y, si el recurso no cambió, el servidor responde con un 304 sin cuerpo — mucho más rápido que descargar de nuevo.
Cómo Configurar Cache-Control en Apache (.htaccess)
La forma más directa en Apache es con mod_headers o mod_expires. El siguiente bloque cubre los casos más frecuentes:
<IfModule mod_headers.c>
# Activos estáticos con hash en el nombre
<FilesMatch "\.(js|css|woff2?|ttf|eot)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# Imágenes y SVG
<FilesMatch "\.(png|jpg|jpeg|gif|webp|svg|ico)$">
Header set Cache-Control "public, max-age=2592000"
</FilesMatch>
# HTML
<FilesMatch "\.html?$">
Header set Cache-Control "no-cache"
</FilesMatch>
</IfModule>
Si usas cPanel, este bloque va en el .htaccess de la raíz de tu dominio. Asegúrate de que mod_headers esté activo — en la mayoría de hostings compartidos de México lo está.
Cómo Configurar Cache-Control en Nginx
En Nginx la directiva equivalente es add_header dentro de bloques location:
location ~* \.(js|css|woff2?)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ~* \.(png|jpg|jpeg|webp|gif|svg|ico)$ {
add_header Cache-Control "public, max-age=2592000";
}
location ~* \.html?$ {
add_header Cache-Control "no-cache";
}
Cómo Enviar Cache-Control desde PHP
Para respuestas dinámicas que quieras cachear (por ejemplo, una API que devuelve datos que cambian cada hora):
<?php
// Cacheable durante 1 hora, tanto en navegador como en CDN
header('Cache-Control: public, max-age=3600, s-maxage=3600');
// Dato sensible del usuario — solo caché privada, nunca en CDN
header('Cache-Control: private, no-store');
?>
Llama a header() antes de cualquier salida. Una vez enviados bytes al cliente, los headers ya no se pueden modificar.
Para una visión más amplia de técnicas de optimización, consulta nuestra guía de rendimiento web con recursos adicionales.
Conclusiones clave
- Cache-Control es la cabecera HTTP moderna que controla cómo y cuánto tiempo los navegadores y CDNs guardan recursos.
- Para activos estáticos con fingerprinting usa
public, max-age=31536000, immutable— el hash en el nombre garantiza que los usuarios siempre descarguen la versión actual al hacer deploy. no-cache≠ "no guardar en caché": significa "revalida antes de servir".no-storees "no guardar en caché".- El HTML y las páginas dinámicas deben usar
no-cachepara evitar que los usuarios vean versiones obsoletas. - Puedes configurar Cache-Control en Apache (
.htaccess), Nginx (bloqueslocation) o directamente en PHP conheader().
¿Tu sitio aún carga recursos estáticos en cada visita? En elenlace.com configuramos políticas de caché optimizadas para tu stack y nos aseguramos de que funcionen correctamente tanto en el servidor como en el CDN.
Preguntas frecuentes
¿Cuál es la diferencia entre Cache-Control y Expires?
Expires es la cabecera antigua que especifica una fecha absoluta de vencimiento. Cache-Control: max-age especifica duración relativa y tiene prioridad cuando ambas están presentes. Hoy en día se recomienda usar solo Cache-Control.
¿Cache-Control afecta el posicionamiento en Google?
No directamente, pero impacta métricas de rendimiento como LCP y TTFB en visitas repetidas, que sí forman parte de las señales de experiencia de página. Una buena política de caché mejora la velocidad real de los usuarios y, en consecuencia, puede mejorar los Core Web Vitals.
¿Cómo verifico que Cache-Control está funcionando?
Abre DevTools de Chrome → pestaña Network → recarga la página y revisa los headers de respuesta de cada recurso. Los recursos bien cacheados mostrarán "(from disk cache)" o "(from memory cache)" en la columna Size en visitas posteriores.
¿Debo usar Cache-Control en páginas de login o checkout?
En páginas con datos personales o de sesión usa Cache-Control: private, no-store. Esto impide que proxies intermedios o CDNs guarden respuestas que contienen información del usuario, evitando fugas de datos entre sesiones.
¿Prefieres que lo hagamos por ti? En El Enlace resolvemos hosting y desarrollo web profesional.
Para saber más
Otros proveedores y guías que vale la pena comparar: