Introducción

Si tu Worker de Cloudflare es el origin de tu aplicación (por ejemplo, con Next.js, Astro o SvelteKit), cada pedido ejecuta tu código aunque el resultado sea idéntico al anterior. Esto aumenta latencia y costos innecesarios. Workers Cache coloca una caché regional tiered directamente frente a tus entrypoints, evitando que el Worker se ejecute si el contenido está fresco. Solo invoca tu código cuando el caché está vacío o expiró, y podés configurarlo con un bloque en wrangler.toml y los headers Cache-Control que ya conocés.

En esta guía, configurarás Workers Cache para un Worker existente, optimizarás el TTL con stale-while-revalidate, manejarás contenido negociado con Vary, y purgarás el caché de forma programática.

Qué es y para qué sirve

Workers Cache es un servicio de caché regional, distribuido globalmente, que actúa como capa intermedia entre los clientes y tu Worker. Sus características clave son:
  • Cero configuración adicional: no requiere zonas, reglas de caché ni productos separados. Se activa con una línea en wrangler.toml.
  • Control por entrypoint: podés habilitar o deshabilitar la caché para endpoints específicos dentro del mismo Worker (por ejemplo, /api/* sin caché y /blog/* con caché).
  • Integración nativa con HTTP: usa los headers estándar Cache-Control, Vary, ETag y stale-while-revalidate para definir políticas de caché.
  • Purgas programáticas: eliminá entradas por tag (etiqueta), prefijo de ruta o ruta exacta desde el Worker.
  • Multi-tenancy seguro: cada entrypoint tiene su propio espacio de nombres en el caché, evitando colisiones entre tenants o sitios.
Casos de uso ideales:
  • Aplicaciones server-rendered que necesitan frescura sin sacrificar velocidad (ej: catálogos de productos, dashboards).
  • Sitios estáticos generados en demanda (SSG dinámico) con refresco periódico.
  • APIs públicas con endpoints que devuelven respuestas cacheables (ej: configuraciones, metadata).
  • Sitios multilingües o con negociación de contenido (ej: /es, /en, /fr).

Prerequisitos

Antes de comenzar, verifica que cumplís estos requisitos técnicos y de permisos:

RequisitoVersión mínimaNotas
**Cloudflare Account**Debés tener un dominio en Cloudflare con Workers habilitado.
**Wrangler CLI**BLOCK36 o superiorInstalalo con BLOCK37.
**Trabajo con Workers**Tenés al menos un Worker desplegado y funcionando.
**Plan de Workers**Todos los planesWorkers Free, Pro, Business y Enterprise soportan Workers Cache.
**Permisos**BLOCK38 y BLOCK39Necesarios en la cuenta de Cloudflare.
**Dominio**El Worker debe estar asociado a un dominio (personalizado o BLOCK40).
**Headers de respuesta**Tu Worker debe respetar los headers BLOCK41 para que la caché funcione.
Verificá tu versión de Wrangler:
wrangler --version
# Ejemplo de salida: wrangler 3.62.0

Si usás un dominio personalizado, asegurate de que el route del Worker esté correctamente configurado en la pestaña Workers de tu dashboard de Cloudflare.

Guía paso a paso

Paso 1: Habilitá Workers Cache en tu Worker

  1. Abrid el archivo wrangler.toml de tu proyecto:
   cd /ruta/a/tu-proyecto-worker
   code wrangler.toml
   
  1. Agregá la siguiente configuración bajo la sección [build] o al final del archivo:
   [cache]
   mode = "default"  # Habilita la caché global para todos los entrypoints
   
Opcional: Si querés controlar la caché por entrypoint (recomendado para APIs o rutas sensibles), usá:
   [[cache.rules]]
   type = "prefix"
   pattern = "/api/*"
   mode = "bypass"  # Deshabilita la caché para /api/*

   [[cache.rules]]
   type = "prefix"
   pattern = "/assets/*"
   mode = "default"  # Habilita la caché para /assets/*
   
  1. Desplegá el cambio:
   wrangler deploy
   
  1. Verificá que la caché esté activa:
– Hacé un pedido a tu Worker y revisá los headers de respuesta:
     curl -I https://tu-dominio.com/
     

– Buscá los headers:

     CF-Cache-Status: HIT  # Indica que la respuesta vino de la caché
     

Si no ves este header, revisá la configuración en wrangler.toml y asegurate de que el Worker esté asociado al dominio correcto.

Paso 2: Configurá la política de caché con headers HTTP

Tu Worker debe devolver headers Cache-Control válidos para que la caché funcione. Los más importantes son:

HeaderValor sugeridoEfecto
BLOCK46BLOCK47 (5 minutos)La respuesta se cachea por 5 minutos. Pasado ese tiempo, la caché se considera *stale*.
BLOCK48BLOCK49 (1 hora)Permite servir contenido *stale* mientras se refresca en segundo plano.
BLOCK50BLOCK51 (1 día)Define el TTL para caches compartidas (como Workers Cache).
BLOCK52BLOCK53Indica que la respuesta puede ser cacheada por cualquier caché (incluyendo Workers Cache).
BLOCK54BLOCK55Fuerza al cliente a validar con el origen antes de servir la caché.
BLOCK56BLOCK57Impide que la respuesta sea cacheada. Útil para datos sensibles.
Ejemplo práctico:
// En tu Worker (ej: index.js)
export default {
  async fetch(request, env) {
    // ... lógica de tu Worker ...
    const response = new Response(html, {
      headers: {
        "Content-Type": "text/html",
        "Cache-Control": "public, max-age=300, stale-while-revalidate=3600",
        "Vary": "Accept-Language"
      }
    });
    return response;
  }
}
Resultados esperados:
  • El primer pedido a /productos generará el HTML y lo cacheará por 5 minutos.
  • Durante esos 5 minutos, cualquier otro pedido a /productos (desde cualquier parte del mundo) devolverá la versión cacheada sin ejecutar el Worker.
  • Pasados los 5 minutos, el próximo pedido:
– Si stale-while-revalidate está configurado, devolverá el contenido stale inmediatamente mientras el Worker regenera la página en segundo plano.

– Si no hay stale-while-revalidate, el Worker se ejecutará y generará una nueva respuesta.

Paso 3: Manejá contenido negociado con Vary

Si tu Worker devuelve respuestas diferentes según el user agent (ej: HTML para navegadores, JSON para APIs), usá el header Vary para cachear variantes separadas:

export default {
  async fetch(request, env) {
    const accept = request.headers.get("Accept");
    const response = new Response(html, {
      headers: {
        "Content-Type": "text/html",
        "Cache-Control": "public, max-age=300",
        "Vary": "Accept"  // Cachea una variante por valor de Accept
      }
    });
    return response;
  }
}
Cómo funciona:
  • Un pedido con Accept: text/html generará una entrada en el caché.
  • Un pedido con Accept: application/json generará otra entrada, evitando que se sirva el HTML a un cliente que espera JSON.
Error común:
  • Si no usás Vary y tu respuesta cambia según el header, la caché devolverá la primera variante a todos los clientes (ej: el HTML de un navegador a un bot de scraping). Siempre definí Vary cuando el contenido sea variable.

Paso 4: Purgá el caché programáticamente

Para forzar la actualización de una entrada en el caché, llamá a la API de purga de Workers Cache desde tu Worker:

// En tu Worker (ej: purge.js)
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    if (url.pathname === "/purge") {
      // Purga por ruta exacta
      const response = await env.CACHE.purgeByUrl(["https://tu-dominio.com/productos"]);
      return new Response(JSON.stringify(response), { status: 200 });
    }
    return new Response("OK");
  }
}
Configuración requerida:
  1. Asociá el Worker a un service binding en wrangler.toml:
   [[services]]
   binding = "CACHE"
   service = "tu-worker-cache"  # Nombre o ID de tu Worker
   
  1. Purgá por tag (etiqueta):
   await env.CACHE.purgeByTag(["productos"]);
   

Tags: definilos en el header Cache-Tag de la respuesta original:

     headers: {
       "Cache-Tag": "productos,inicio"
     }
     
  1. Purgá por prefijo de ruta:
   await env.CACHE.purgeByPrefix("/blog/*");
   
Respuesta esperada:
{
  "success": true,
  "aantal": 42  // Cantidad de entradas purgadas
}
Notas:
  • La purga es eventualmente consistente: puede tardar hasta 30 segundos en propagarse globalmente.
  • Usá purgas por tag o prefijo para minimizar el impacto en el caché.

Paso 5: Optimizá el TTL para tu caso de uso

Definí max-age y stale-while-revalidate según la frecuencia de actualización de tu contenido:

Tipo de contenidoBLOCK72BLOCK73Ejemplo de uso
Catálogo de productosBLOCK74 (5 min)BLOCK75 (1 hora)Los precios cambian cada pocos minutos.
Blog (artículos)BLOCK76 (1 día)BLOCK77 (30 días)Los artículos rara vez cambian.
Dashboard de usuarioBLOCK78 (1 min)BLOCK79 (5 min)Datos en tiempo real pero con tolerancia a stale.
APIs públicasBLOCK80 (1 semana)BLOCK81Respuestas estables (ej: metadata).
Ejemplo en código:
headers: {
  "Cache-Control": "public, max-age=300, stale-while-revalidate=3600"
}
Resultado:
  • Los primeros 5 minutos: contenido fresco servido desde el caché.
  • Entre 5 minutos y 1 hora: contenido stale servido inmediatamente, mientras el Worker regenera la página en segundo plano.
  • Pasada 1 hora: el próximo pedido generará una respuesta fresca.

Paso 6: Validá el comportamiento con CF-Cache-Status

Cada respuesta de Workers Cache incluye el header CF-Cache-Status para diagnosticar el estado de la caché:

ValorSignificado
BLOCK84La respuesta vino del caché.
BLOCK85La respuesta no estaba en el caché; el Worker se ejecutó.
BLOCK86Durante BLOCK87: se está refrescando el caché en segundo plano.
BLOCK88La ruta no está configurada para cachear (ej: BLOCK89).
BLOCK90El contenido está *stale* y no se está refrescando.
Ejemplo de diagnóstico:
curl -I https://tu-dominio.com/productos
# Respuesta:
# CF-Cache-Status: HIT
# Age: 120  # Segundos desde que se cacheó la respuesta

Paso 7: Integra Workers Cache con tu CDN actual

Si ya usás Cloudflare CDN para assets estáticos (ej: /assets/*), podés combinar ambas capas de caché:

  1. Desactivá la caché de CDN para rutas dinámicas:
En el dashboard de Cloudflare, ve a Rules > Page Rules y creá una regla:

URL pattern: https://tu-dominio.com/api/*

Setting: Bypass Cache

Setting: Disable Security

  1. Dejá activada la caché de CDN para rutas estáticas:
   [[cache.rules]]
   type = "prefix"
   pattern = "/assets/*"
   mode = "default"
   
  1. Priorizá Workers Cache sobre CDN:
– Workers Cache se ejecuta antes que el CDN tradicional, por lo que tiene prioridad.

– Si un pedido a /productos está en Workers Cache, no pasará por el CDN.

Consideraciones y buenas prácticas

Limitaciones y alternativas

LimitaciónTrabajoarround
**Tamaño máximo de caché**: 50MB por entrada.Dividí respuestas grandes en fragmentos más pequeños.
**TTL mínimo**: 0 segundos (sin caché).Usá BLOCK94 si necesitás respuestas siempre frescas.
**No soporta cookies**: Las respuestas con cookies no se cachean.Mueve cookies a headers personalizados (ej: BLOCK95).
**Purgas programáticas limitadas**: Solo por URL, tag o prefijo.Diseñá tu arquitectura para minimizar purgas (ej: por tag).
### Seguridad y caché
  • Datos sensibles: Nunca cacheés respuestas con información sensible (ej: tokens, contraseñas). Usá Cache-Control: no-store.
  • CSRF: Si tu Worker maneja formularios, asegurate de que los tokens CSRF no sean cacheados. Incluílos en el header Vary:
  headers: {
    "Vary": "CSRF-Token"
  }
  
  • CORS: Si tu Worker responde a solicitudes cross-origin, definí Vary: Origin para cachear variantes por origen:
  headers: {
    "Vary": "Origin"
  }
  

Monitoreo y métricas

Cloudflare no expone métricas detalladas de Workers Cache en el dashboard, pero podés usar:

  • Logs de Workers: Activá los logs para tu Worker y filtrá por CF-Cache-Status.
  [observability]
  enabled = true
  
  • Workers Analytics Engine: Para métricas avanzadas (ej: cantidad de hits vs misses).
  • Custom Metrics: Registrá eventos en tu Worker:
  export default {
    async fetch(request, env) {
      const cacheStatus = request.headers.get("CF-Cache-Status") || "MISS";
      env.METRICS.log({
        event: "cache_status",
        status: cacheStatus
      });
      // ... resto del código ...
    }
  }
  

Migración desde otras soluciones de caché

Si ya usás:

  • Cloudflare Cache Rules: Workers Cache reemplaza esta funcionalidad. Eliminá las reglas antiguas.
  • CDN tradicional: Workers Cache actúa como una capa más rápida (por estar en la misma región que el Worker). No necesitas configurar nada adicional.
  • Varnish o Nginx: Workers Cache es más simple y no requiere mantenimiento de servidores. Migrá tus reglas de caché a headers Cache-Control.

Conclusión

Workers Cache transforma tu Worker en un origin inteligente, reduciendo latencia y costos de CPU sin sacrificar frescura. Con una línea en wrangler.toml y los headers Cache-Control que ya usás, podés:

  1. Cachear respuestas dinámicas (como páginas de e-commerce o dashboards).
  2. Usar stale-while-revalidate para servir contenido stale mientras se refresca en segundo plano.
  3. Cachear variantes de contenido con Vary.
  4. Purgar el caché programáticamente por URL, tag o prefijo.
Próximos pasos:
  • Probalo en un entorno de staging antes de aplicarlo a producción.
  • Revisá los logs de tu Worker para ajustar los TTL según el comportamiento real.
  • Explorá las APIs avanzadas de Workers Cache para casos de uso complejos (ej: caché por tenant en Workers for Platforms).

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *