En Kinsta, estamos obsesionados con la velocidad: Nuestros servicios de Alojamiento de Aplicaciones, Alojamiento de Bases de Datos y Alojamiento Administrado de WordPress se ejecutan en la red de Nivel Premium y las máquinas C2 más rápidas de Google Cloud Platform, y confiamos en Cloudflare para mantener el acelerador a fondo para decenas de miles de clientes que quieren distribuir su contenido por todo el mundo con velocidad y seguridad.

Al hacerlo posible, hemos aprendido un par de cosas sobre el uso de Cloudflare Workers y Workers KV para proporcionar reglas de almacenamiento en caché optimizadas para contenido estático y dinámico.

A principios de 2023, redoblamos los esfuerzos en la gestión de la caché de Cloudflare, haciendo que las cachés respondieran mejor a los cambios de configuración del cliente, al tiempo que trasladábamos el trabajo duro de la difusión de actualizaciones de funciones de nuestros administradores del backend a Cloudflare Workers. Un resultado clave fue un aumento espectacular de la proporción de datos de clientes almacenados con éxito en caché, que aumentó un 56,3% entre octubre de 2022 y marzo de 2023.

Datos que reflejan un incremento porcentual de aciertos exitosos en caché con el tiempo.
La optimización a través de Cloudflare Workers se convirtió en un objetivo más importante en enero de 2023.

Cloudflare Workers y Workers KV nos permiten personalizar mediante programación cada solicitud y respuesta con un esfuerzo mínimo y menor latencia. Ya no necesitamos desplegar cambios en cientos de miles de contenedores cuando queremos implementar nuevas funciones; podemos replicar o implementar la función con Workers y desplegarla en todas partes con unos pocos comandos y clics, ahorrándonos días de trabajo y mantenimiento.

Enrutamiento de Peticiones con Workers KV y Workers

Cada dominio alojado en Kinsta es una clave, y su valor contiene al menos la configuración principal, como la IP y el puerto del origen, y un ID aleatorio único. Con estos datos fácilmente disponibles en Workers KV, podemos utilizar Workers para analizar, manipular y dirigir las solicitudes a su backend esperado. También utilizamos Workers KV para almacenar las opciones de optimización del cliente, como Polish, Redimensionamiento de imágenes y Auto Minify.

Para dirigir las solicitudes a IP y puertos personalizados, utilizamos resolveOverride, una propiedad Request específica de Cloudflare. Aquí tienes un ejemplo:

// Assign KV values to variables
const { customBackend } = kvdata.kinstaConf;

// Override the backend
cf.resolveOverride = customBackend;

Sin embargo, aunque Workers KV funcionaba bien para enrutar las solicitudes, pronto observamos respuestas incoherentes en nuestra caché. A veces, un cliente activaba Polish y, debido a la caché de un minuto de Workers KV, llegaban nuevas solicitudes antes de que Workers KV propagara completamente el cambio, lo que hacía que almacenáramos en caché activos no optimizados. Cuando esto ocurría, el cliente tenía que volver a borrar su caché manualmente. No era lo ideal. Los clientes se frustraban, y nosotros malgastábamos operaciones de la API y ancho de banda de GCP, purgando cachés constantemente.

La Clave de Caché es la Clave

Como siempre leemos los datos de Workers KV del dominio, nos dimos cuenta de que podríamos direccionar las solicitudes y personalizar la clave de caché, añadiendo cosas como el ID del dominio y características que podrían afectar el recurso, como Polish. Hoy en día, nuestra clave de caché está muy personalizada para reflejar rápidamente los cambios de cada cliente en nuestro panel o API. Al modificar la clave de caché utilizando los datos de Workers KV, ya nadie tiene que preocuparse de limpiar la caché. Tan pronto como Workers KV propaga los cambios, la clave de caché también cambia, y solicitamos y almacenamos en caché un activo nuevo.

La forma más sencilla de personalizar la clave de caché es añadirle query params. Por ejemplo:

let cacheKey = `${request.url}?custom-cache-param-polish=lossy`

Por supuesto, tienes que comprobar la URL en busca de parámetros existentes para determinar qué conector utilizar – ? o & – y asegurarte de que estás utilizando un identificador único.

Después, puedes utilizar esta nueva clave de caché para guardar la respuesta con la API de caché o con Fetch, o con ambas.

Caché Workers KV

Las operaciones Workers KV son asequibles, pero las cifras pueden acumularse cuando desencadenas miles de millones de operaciones de lectura al día.

Gracias a la personalización de nuestra clave de caché, nos dimos cuenta de que podíamos almacenar en caché los datos de Workers KV con Cache API, ahorrando en operaciones de lectura y posiblemente reduciendo la latencia al evitar múltiples peticiones GET de Workers KV por visitante. Dado que la respuesta almacenada en caché se basa ahora en la URL de la solicitud combinada con los datos KV, ya no tenemos que preocuparnos de almacenar en caché contenido obsoleto.

Gráfico que muestra el flujo del proceso cuando se almacenan en caché los datos de Workers KV.
Se incluye el flujo del proceso con el almacenamiento en caché de los datos KV de Workers.
Gráfico que muestra las respuestas TTFB para varios escenarios de caché.
Tiempo medio hasta el primer byte en varios escenarios de almacenamiento en caché.

Sin embargo, a diferencia de muchas aplicaciones, no podemos almacenar en caché Workers KV durante periodos prolongados. Los clientes de Kinsta prueban constantemente nuevas funciones, cambian la configuración de Polish y Auto Minify, a veces excluyendo páginas o extensiones de la caché, y quieren ver sus cambios en producción lo antes posible.

Fue entonces cuando decidimos almacenar en microcache los datos de Workers KV — almacenando en caché contenidos dinámicos o que cambian constantemente durante un periodo de tiempo muy corto, normalmente inferior a 60 segundos.

Es bastante sencillo implementar tu propia lógica de almacenamiento en caché de Workers KV. Por ejemplo:

const handleKVCache = async (event, myCustomDomain) => {
  // Try to get KV from cache first
  const cache = caches.default;
  let site_data = await cache.match( `https://${myCustomDomain}/some-string-ID-kv-data/` );

  // Valid KV cache match
  if (site_data && site_data.status === 200) {
    // ... modify your cached data if necessary, then return it
    return site_data;
  }

  // Invalid cache (expired, miss, etc), get data from KV namespace
  site_data = await KV_NAMESPACE.get(myCustomDomain.toLowerCase());
  
  // Cache valid KV responses with Cache API
  if (site_data) {
    let kvResponse = new Response(JSON.stringify(site_data), {status: 200});
    kvResponse.headers.set("Cache-Control", "public, s-maxage=30");
    event.waitUntil(cache.put(`https://${myCustomDomain}/some-string-ID-kv-data/`, kvResponse));
  }
  
  return site_data;
};

(Opcionalmente, podrías utilizar BetterKV de FlareUtils.)

En Kinsta, implementamos un TTL de caché de 30 segundos para los datos de Workers KV, disminuyendo las operaciones de lectura en aproximadamente un 80%.

Gráfico que muestra la evolución de las operaciones de lectura a lo largo del tiempo.
Disminución de las operaciones de lectura tras implementar un TTL de 30 segundos para la caché de datos Workers KV.

Más Información

¿Quieres saber más sobre Workers y Workers KV? Consulta la documentación para desarrolladores de Cloudflare Workers KV o visita la página de inicio de Cloudflare dedicada a Workers KV.

Este artículo se publicó originalmente en el sitio web de Cloudflare.

Paulo Paracatu

Paulo is a seasoned DevOps Engineer at Kinsta with a solid web hosting and optimization background. Equipped with Bash and JavaScript expertise, he uses Cloudflare Workers to continually improve user experiences in hosting.