Comportamiento por defecto de la caché

Ver en Markdown

Qué peticiones tiene en cuenta la caché del borde, qué respuestas guarda, cuánto tiempo las conserva y qué nunca cachea.

En esta página

La caché decide dos veces: primero con la petición (¿es elegible, es decir, se consulta la caché?) y después con la respuesta (¿se puede guardar y durante cuánto tiempo?).

Peticiones elegibles

Una petición solo se busca en la caché si se cumple todo esto. Si no, va directa al origen y se marca como DYNAMIC.

  • La caché está activada para el nombre y el modo desarrollo no.
  • El método es GET o HEAD, sin cabecera Upgrade (WebSocket) y sin cuerpo.
  • No coincide ninguna regla de caché bypass.
  • La extensión de la ruta está en la lista por defecto de abajo, o una regla cache hace elegible la petición.
  • La ruta no es ambigua: sin parámetros de ruta con ;, sin /, \, NUL, CR ni LF codificados, sin barra invertida y sin un último segmento que acabe en punto (/x.css.).

La Cache-Control y el Pragma de la propia petición se ignoran, así que un cliente no puede obligar al borde a volver a pedir al origen.

Extensiones por defecto

7z avi avif apk apng bin bmp bz2 class css csv doc docx dmg ejs eot eps exe flac gif gz ico iso jar
jpeg jpg js jxl m4a m4v mid midi mjs mkv mov mp3 mp4 ogg otf pdf pict pls png ppt pptx ps rar svg
svgz swf tar tif tiff ttf wasm webm webmanifest webp woff woff2 xls xlsx zip zst

además de robots.txt. El HTML, el JSON, el XML, txt y los source maps no están en la lista: necesitan una regla cache.

Frescura: cuánto tiempo se guarda una respuesta

El borde toma el TTL de la primera de estas cabeceras que envíe el origen:

  1. OpenWAF-CDN-Cache-Control: un cache-control solo para el borde de OpenWAF, que nunca se reenvía a los navegadores.
  2. CDN-Cache-Control (RFC 9213), que se reenvía tal cual.
  3. Cache-Control: s-maxage y después max-age.
  4. Expires.
  5. Los valores por defecto de abajo, si no hay ninguna de las anteriores.

La Cache-Control siempre llega al navegador tal como la envió el origen, salvo que configures un TTL del navegador.

TTL por defecto

Sin ninguna cabecera de frescura, y solo para la lista de extensiones por defecto:

EstadoTTL en el borde
200, 206, 3012 horas
302, 30320 minutos, solo en peticiones sin Cookie ni Authorization
404, 4103 minutos
Cualquier otrono se guarda

Los directorios de build conocidos de los frameworks habituales reciben 7 días en lugar de 2 horas: /_next/static/, /_nuxt/, /_astro/, /_app/immutable/, /build/assets/ y /packs/, salvo los ficheros que cambian a propósito, como version.json, latest.json, sw.js, service-worker, manifest.json, page-data/ y app-data.json.

Una ruta que una regla hace elegible (HTML, JSON…) no recibe TTL por defecto: necesita frescura del origen o un TTL en la regla.

Ningún objeto se conserva más de 30 días.

Respuestas que nunca se guardan

Estas respuestas llegan al visitante sin guardarse y se marcan como BYPASS:

  • Cache-Control: no-store o private. Con private="Set-Cookie", la respuesta se guarda sin esa cabecera.
  • Una cabecera Set-Cookie, salvo que una regla fije el TTL del borde (entonces se quita Set-Cookie de la copia guardada).
  • Una petición con Authorization cuya respuesta no diga public, s-maxage ni must-revalidate.
  • Un Vary que nombre algo distinto de Accept-Encoding, Accept (solo imágenes) u Origin, incluidos Vary: * y Vary: Cookie. Consulta Claves de caché.
  • Un código de estado que no se puede cachear, un cuerpo mayor que el tamaño máximo de objeto (100 MB por defecto) o una codificación distinta de gzip o Brotli.
  • Documentos personales: para pdf, doc(x), xls(x), ppt(x), csv, zip, 7z, rar, tar y gz, una petición con Cookie o Authorization solo se guarda si el origen envió frescura explícita.
  • Las páginas que genera el propio borde: retos, páginas de bloqueo, la puerta de acceso y las redirecciones.

Armadura anti-engaño de caché

Activada por defecto. Cuando la extensión de la URL promete un tipo pero el origen responde text/html, application/json, application/xhtml+xml o text/plain (salvo robots.txt y .csv), la respuesta no se guarda. Así se corta el ataque clásico en el que /account.php/x.css devuelve una página HTML personal que, si no, se cachearía y se serviría a otros. Se admiten las discrepancias inofensivas, como application/octet-stream o un .jpg servido como image/webp.

Revalidación y contenido caducado

  • no-cache, max-age=0 o s-maxage=0 con ETag o Last-Modified: la respuesta se guarda y se revalida con el origen cada vez que se usa (If-None-Match / If-Modified-Since); un 304 evita volver a enviar el cuerpo.
  • Un objeto caducado con validadores se revalida: REVALIDATED si llega un 304 y EXPIRED si llega un 200 nuevo.
  • Caducado mientras se revalida: con el stale-while-revalidate del origen, el objeto caducado se sirve (UPDATING) mientras se actualiza en segundo plano.
  • Caducado si hay error: cuando el origen falla (error de red, tiempo agotado, 500, 502, 503, 504), se sirve el objeto caducado (STALE) durante el stale-if-error del origen o, si no lo envía, hasta 24 horas por defecto.
  • must-revalidate, proxy-revalidate, no-cache y s-maxage desactivan el contenido caducado.

Range, HEAD y fallos simultáneos

  • Un GET con un único Range que no está en caché pide el objeto entero una sola vez, lo guarda y responde el rango a medida que llega (206), así que los vídeos también se cachean.
  • Un HEAD se sirve desde la caché si el objeto está; si no, va al origen y no se guarda nada.
  • Cuando muchos visitantes piden a la vez el mismo objeto que no está en caché, solo una petición va al origen; las demás esperan hasta 5 segundos y se sirven con el resultado.

Compresión

El borde pide al origen br, gzip y guarda una sola copia por URL en la codificación que eligió el origen. Si el navegador de un visitante no acepta esa codificación, recibe la copia descomprimida al vuelo; Vary: Accept-Encoding no divide la caché.

Última actualización:

↑↓ para moverte↵ para abriresc para cerrar