// Engineering Log
HTTPS y servidor web en la práctica: Parte 4 — Almacenamiento en caché HTTP y CDN: Cache-Control, ETag, proxy_cache y purga de caché
Publicado el 06.11.2026 · Autor: Mikhail Gorbachev
// Ruta rápida
Este artículo pertenece al tema Servidores e infraestructura.
El almacenamiento en caché — la forma más barata de acelerar un sitio y reducir la carga del servidor: una respuesta que no necesita volverse a generar ni transmitir llega al instante. Pero la caché tiene una cara B — los usuarios ven estilos antiguos después del despliegue, un CDN sirve la página personal de un visitante a otro, y los cambios en el sitio «no se aplican». Casi todos esos problemas se resuelven con los encabezados Cache-Control correctos y entendiendo dónde se almacena exactamente la copia. Un resumen breve de los encabezados de caché está en el artículo «Encabezados HTTP»; aquí — cómo usarlos.
Dónde se almacenan las copias
Entre el usuario y la aplicación suele haber varias cachés:
- Caché del navegador — personal, solo para un usuario.
- CDN (Cloudflare, CDN en la nube y CDN rusos) — caché compartida en servidores por todo el mundo; una copia se sirve a todos los visitantes.
- Proxy inverso — Nginx con
proxy_cache, Varnish — caché compartida cerca de la aplicación. - Caché dentro de la aplicación — Redis, memcached, caché de páginas en CMS. No tiene relación con los encabezados HTTP.
Las reglas para los tres primeros las establece el servidor en los encabezados de respuesta. Las cachés compartidas (CDN, proxy) por defecto son más prudentes que el navegador, y los CDN tienen ajustes propios que pueden sobrescribir los encabezados.
Cómo decide la caché qué hacer
La copia en caché puede ser fresca o obsoleta. Una copia fresca se entrega sin consultar al servidor. Una copia obsoleta se verifica primero — con una petición condicional If-None-Match (por ETag) o If-Modified-Since (por Last-Modified). Si el recurso no cambió, el servidor responde con un breve 304 Not Modified sin cuerpo, y la caché renueva la copia.
Cuánto tiempo permanece fresca lo define Cache-Control: max-age en segundos. Si no hay ni Cache-Control ni Expires, las cachés pueden estimar el tiempo por su cuenta — normalmente 10 % del tiempo desde Last-Modified. Un archivo modificado hace un año puede ser considerado fresco por el navegador más de un mes. Por eso siempre hacen falta encabezados explícitos.
Directivas Cache-Control
| Directiva | Significado |
|---|---|
max-age=N | fresco N segundos |
s-maxage=N | igual, pero solo para cachés compartidas; tiene prioridad sobre max-age |
no-cache | se puede almacenar, pero antes de usarlo comprobar con el servidor |
no-store | no almacenar en ningún sitio |
private | solo el navegador; las cachés compartidas no pueden |
public | se puede almacenar en cachés compartidas, incluso si la petición tenía Authorization |
must-revalidate | una copia obsoleta no puede entregarse sin verificación, incluso si el servidor no está disponible |
immutable | el recurso no va a cambiar — no verificar ni siquiera al recargar la página |
stale-while-revalidate=N | N segundos tras quedar obsoleta, entregar la copia antigua mientras se actualiza en segundo plano |
stale-if-error=N | N segundos entregar la copia antigua si el servidor responde con error |
Para los CDN existe un encabezado separado CDN-Cache-Control (RFC 9213): actúa solo sobre el CDN y no es visible para el navegador. Así se puede mantener una página en el CDN una hora y en el navegador — sin caché.
Estrategias comunes
Estáticos con hash en el nombre (app.3f9a1c.js, style.8b2e.css — así empaquetan Vite, webpack, Hugo Pipes): al cambiar el archivo cambia el nombre, por eso la copia antigua se puede mantener para siempre.
Cache-Control: public, max-age=31536000, immutablePáginas HTML: los enlaces a las nuevas versiones de los recursos estáticos están en el HTML, por eso el HTML debe actualizarse inmediatamente.
Cache-Control: no-cache
ETag: "5f2a-18c4"El navegador guarda la página, pero la comprueba cada vez: si no cambió — 304 sin cuerpo.
Estáticos sin hash (imágenes desde un CMS, favicon.ico, robots.txt): tiempo corto y verificación.
Cache-Control: public, max-age=3600, stale-while-revalidate=86400Páginas personales y respuestas API con datos del usuario:
Cache-Control: private, no-storeDatos públicos de API que cambian con frecuencia (cotizaciones, existencias):
Cache-Control: public, max-age=10, stale-while-revalidate=30Configuración en Nginx
Encabezados para estáticos y HTML:
location ~* \.(?:js|css|woff2)$ {
# solo para archivos con hash en el nombre
add_header Cache-Control "public, max-age=31536000, immutable" always;
}
location ~* \.(?:png|jpe?g|webp|avif|svg|ico)$ {
add_header Cache-Control "public, max-age=86400" always;
}
location / {
add_header Cache-Control "no-cache" always;
try_files $uri $uri/ /index.html;
}Nginx por sí solo sirve ETag y Last-Modified para archivos estáticos y responde 304 a peticiones condicionales. Para respuestas de la aplicación, ETag debe ponerlo la propia aplicación.
Caché en Nginx: proxy_cache
Nginx puede almacenar respuestas de la aplicación y servirlas sin consultar al backend:
proxy_cache_path /var/cache/nginx/app levels=1:2 keys_zone=app:50m
max_size=2g inactive=7d use_temp_path=off;
server {
location / {
proxy_pass http://127.0.0.1:8080;
proxy_cache app;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_valid 200 301 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
# no cachear para usuarios autenticados
proxy_cache_bypass $cookie_sessionid;
proxy_no_cache $cookie_sessionid;
add_header X-Cache-Status $upstream_cache_status always;
}
}proxy_cache_use_stale— en caso de error de la aplicación servir una copia obsoleta: el sitio sigue disponible mientras la aplicación se reinicia;proxy_cache_background_updateyupdating— actualizar la copia obsoleta en segundo plano, sirviendo la antigua (análogo astale-while-revalidate);proxy_cache_lock— ante un fallo de caché hacia la aplicación va una sola petición, las demás esperan su resultado. Protege contra avalanchas de peticiones cuando una página popular sale de la caché;X-Cache-StatusmostraráHIT,MISS,EXPIRED,STALE,UPDATINGoBYPASS.
Nginx respeta los encabezados de la aplicación: no cachea respuestas con Set-Cookie, con Cache-Control: private, no-store, no-cache, y el tiempo de Cache-Control: max-age lo sitúa por encima de proxy_cache_valid.
Microcaché — caché de un segundo (proxy_cache_valid 200 1s) para páginas públicas bajo carga: con mil peticiones por segundo, al backend llega una, y los datos se desactualizan como máximo un segundo.
CDN
Qué es importante saber sobre los CDN:
- Los CDN cachean según sus propias reglas. Cloudflare por defecto cachea solo estáticos por extensión de archivo (
.js,.css, imágenes, fuentes), pero no HTML. Para cachear páginas hay que crear una regla de caché (Cache Rules). Otros CDN pueden, en cambio, cachear todo lo que permitan los encabezados; - la clave de la caché — normalmente host, ruta y query string. Parámetros como
utm_source,fbclid,yclidcrean miles de copias de la misma página — en la configuración del CDN conviene excluirlos de la clave; - cookies. Si la respuesta depende de cookies y el CDN la cachea por URL, un visitante puede recibir la página de otro. Respuestas personales — solo
privateo evitar caché si existe la cookie de sesión; - el estado de la caché se ve en los encabezados: en Cloudflare —
CF-Cache-Status(HIT,MISS,EXPIRED,DYNAMIC— no cacheada por reglas,BYPASS— evitada por encabezados de respuesta), en otros —X-Cache, y el encabezadoAgemuestra la antigüedad de la copia.
Comprobación:
curl -sI https://example.ru/assets/app.3f9a1c.js | grep -iE 'cache-control|cf-cache-status|x-cache|age|etag'Repite la petición: con la configuración correcta la segunda vez será HIT y Age será distinto de cero.
Purgado de caché
- Nombres de archivos con hash — la forma principal para estáticos: no hace falta purgar nada, la nueva versión tiene nueva dirección.
- Parámetro de versión (
style.css?v=42) — funciona si el CDN tiene en cuenta el query string en la clave; es peor que el hash porque la versión se cambia manualmente. - Purge en el CDN — vía panel o API, por URLs o por completo. Tras un despliegue es útil purgar el HTML; purgar «todo» después de cada despliegue elimina el beneficio del caché estático.
- Nginx proxy_cache — borrar el directorio de caché o archivos individuales; en la versión gratuita de Nginx no hay comando para purgar por URL, eso lo proporcionan módulos terceros o Nginx Plus.
- No se puede forzar el vaciado del caché del navegador desde el servidor. Si enviaste un archivo con
max-age=31536000sin hash en el nombre, los usuarios verán la versión antigua hasta que caduque el plazo o limpien la caché. El encabezado de respuestaClear-Site-Data: "cache"borra la caché del sitio en el navegador, pero solo cuando el navegador reciba esa respuesta — y la página que está en caché el navegador no la solicita al servidor. Por eso un tiempo largo es solo para archivos con hash.
Errores típicos
- No hay
Cache-Controlen absoluto — los navegadores hacen caché por heurística, y después del despliegue parte de los usuarios ve la maquetación antigua. max-agepor un año parastyle.csssin hash en el nombre — los cambios no llegan a los visitantes que regresan.- HTML cacheado durante largo tiempo — la página referencia archivos remotos de una build antigua, el sitio «se rompe» para parte de los usuarios.
- Página personal sin
privatedetrás de un CDN que cachea HTML — fuga de datos entre usuarios. no-cacheen lugar deno-storedonde los datos no deben almacenarse en disco en absoluto.- Purgar todo el caché del CDN en cada despliegue — tras el despliegue todas las peticiones van al servidor a la vez.
- Depurar «por qué no se actualizó» con la caché del navegador activada — comprueba con curl o con Disable cache en DevTools.
// Tarea parecida
Si estás resolviendo algo parecido
Este artículo pertenece a uno de los temas principales de trabajo. Puedes seguir leyendo sobre el tema, ir a la página principal para entender a qué me dedico o abrir directamente los servicios.
Tema del artículo
Servidores e infraestructura
VPS, Linux, stack web, migraciones, hosting, bases de datos y operacion base.
Tareas frecuentes de este tema
- Migrar un sitio o servicio a un nuevo servidor
- Configurar Linux, Nginx, base de datos y copias de seguridad
- Entender por que el sistema funciona de forma inestable
// Siguiente paso
Si necesitas ayuda con este tema y no solo otro artículo, es mejor ir directo a la página del servicio. La página principal y la selección de materiales quedan como rutas secundarias.
Abrir servicios// Reviews
Reseñas relacionadas
Gracias a Mijaíl por su disposición. Hablamos por teléfono; me explicó cómo hacerlo yo mismo. Es la segunda vez que recurro a él: todo genial y muy rápido.
Gracias a Михаил por su amabilidad. Hablamos por teléfono, me explicó cómo hacerlo por mi cuenta. Es la segunda vez que recurro, todo genial y rápido.
Quiero expresar mi enorme agradecimiento al especialista que me configuró las URLs amigables en OpenCart. Fue fácil y sencillo, y me alegra haber encontrado finalmente a un profesional que lo hizo todo con calidad y sin complicaciones. Antes cambié a cuatro especialistas y cada vez surgían problemas con la configuración, pero esta persona resolvió la tarea a la perfección.
Quiero expresar mi enorme agradecimiento al especialista que me configuró las URLs amigables en OpenCart. Configurar las URLs amigables resultó fácil y sencillo, y me alegra haber finalmente encontrado a un profesional …
Excelente trabajo, no es la primera vez que recurro; encuentra soluciones a problemas complejos. Lo recomiendo.
Excelente trabajo, recurro no por primera vez, encuentra soluciones a problemas complejos. Recomiendo.
¡Excelente trabajo! Cumplió con la tarea a tiempo y sin errores. Fue un placer colaborar, lo recomiendo.
¡Excelente trabajo! Completó la tarea encomendada a tiempo y sin errores. Fue un placer colaborar, lo recomiendo.
Excelente especialista, se adentró en el problema, lo entendió y lo solucionó. Lo recomiendo.
Excelente especialista, se involucró en el problema, lo entendió y lo solucionó. Recomiendo.
Corrección de la expresión regular en location de nginx
21.03.2024 · ★ 5/5
Había que resolver un problema con el certificado SSL en el servidor, que había sido emitido mediante Ngnix Proxy manager. Mijaíl aclaró todos los detalles de cómo tengo todo configurado, pidió accesos para evaluar la viabilidad de la solución, ya que antes no se había enfrentado a un servicio similar. Se familiarizó rápidamente y resolvió mi problema. Colaboración perfecta)
Necesitaba resolver un problema con el certificado SSL en el servidor, que fue emitido a través de Ngnix Proxy manager. Mikhail aclaró todos los detalles sobre cómo tengo todo organizado, pidió accesos para evaluar la …
Diagnóstico de Nginx Proxy Manager en un contenedor Docker y solución del problema
15.03.2024 · ★ 5/5
// Contact
¿Necesitas ayuda?
Escríbeme y te ayudaré a resolver el problema
Respondo en un día laborable (03:00-13:00 GMT)
O deje su solicitud aquí:
// Related