Volver al Blog

Cómo la caché regional de OpenNext reduce la CPU de los Workers en cada acierto de caché

2026-04-254 min read

Next.js está diseñado para ejecutarse en Vercel por defecto. Espera un sistema de archivos, un servicio de optimización de imágenes y un modelo de tiempo de ejecución particular. Para ejecutar Next.js en cualquier otro lugar, como Cloudflare Workers, necesitas un adaptador que conecte esas expectativas con los primitivos de la plataforma de destino.

OpenNext es el proyecto de código abierto que hace exactamente eso. Comenzó como un adaptador de Next.js para AWS Lambda y ahora también ofrece adaptadores oficiales para Cloudflare y Netlify. El paquete que nos interesa aquí es @opennextjs/cloudflare, que te permite desplegar una aplicación Next.js en Cloudflare Workers y conecta la capa de caché de Next.js con los primitivos de almacenamiento de Cloudflare.

Si has seguido la configuración recomendada de Cloudflare para OpenNext, tu open-next.config.ts conecta dos de esos primitivos. Workers KV almacena el HTML cacheado de tus páginas pre-renderizadas. D1 almacena los metadatos de las etiquetas de caché que revalidateTag() escribe. (Por defecto, defineCloudflareConfig() utiliza cachés "dummy" que no hacen nada; KV y D1 son los reemplazos recomendados que conectas tú mismo).

Tanto KV como D1 son servicios remotos. Ambos consumen CPU real en cada solicitud, incluso cuando la página no ha cambiado en días. withRegionalCache es el envoltorio que soluciona eso.

Qué es

withRegionalCache se distribuye con @opennextjs/cloudflare como una sustitución que envuelves alrededor de tu implementación de caché incremental existente. Es un cambio de una sola importación y un solo envoltorio en open-next.config.ts.

import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import kvIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache";
import { withRegionalCache } from "@opennextjs/cloudflare/overrides/incremental-cache/regional-cache";
import d1TagCache from "@opennextjs/cloudflare/overrides/tag-cache/d1-next-tag-cache";

export default defineCloudflareConfig({
incrementalCache: withRegionalCache(kvIncrementalCache, {
mode: "long-lived",
bypassTagCacheOnCacheHit: true,
}),
tagCache: d1TagCache,
});

Funciona de manera similar con r2IncrementalCache o staticAssetsIncrementalCache si esos son los backends que has elegido. El envoltorio es independiente de la caché subyacente que utilices.

Qué hace

Dos cosas, ambas dignas de entender.

1. Una capa de API de caché de Workers delante de KV

El primer comportamiento es una capa de caché regional que utiliza caches.default, la API de caché de Workers. La API de caché es local a cada centro de datos de Cloudflare. No está replicada globalmente, pero ese es el objetivo. Las lecturas de caches.default son esencialmente gratuitas en términos de CPU y terminan en 1 a 5 ms.

Por lo tanto, cuando llega una solicitud para una página cacheada, el worker comprueba primero la API de caché del centro de datos local. Si la entrada está allí, la devuelve inmediatamente. Si no, recurre a KV (una lectura global de ~30 a 100 ms), rellena la API de caché local para la próxima vez y devuelve la respuesta.

La opción mode: "long-lived" mantiene las entradas regionales durante un máximo de 30 minutos por defecto, lo que funciona bien para páginas ISR/SSG.

2. Opcional bypass de D1 tag-cache en aciertos

El segundo comportamiento es opcional: bypassTagCacheOnCacheHit: true.

Por defecto, cada solicitud a una página cacheada también consulta D1 para comprobar si alguna de las etiquetas de revalidación de esa página ha sido invalidada. Las lecturas de D1 tardan ~30 a 200 ms de tiempo real y consumen CPU en la configuración de la consulta y el análisis de resultados.

Con el bypass habilitado, el worker omite ese viaje de ida y vuelta a D1 en los aciertos de caché. La contrapartida: si llamas a revalidateTag(), la caché regional puede seguir sirviendo la versión anterior de una página hasta que expire su entrada regional. Para contenido que no cambia minuto a minuto, eso es invisible para los usuarios.

Cómo ayuda

Sin el envoltorio, un "acierto de caché" típico se ve así en el worker:

  1. Despertar el aislamiento.
  2. Consultar D1 para invalidaciones de etiquetas en esta URL.
  3. Leer el HTML cacheado de KV.
  4. Construir la respuesta y devolverla.

Dos viajes remotos de ida y vuelta y trabajo de CPU significativo, en cada solicitud.

Con el envoltorio:

  1. Despertar el aislamiento.
  2. Leer de la API de caché local.
  3. Devolver.

El mismo resultado desde la perspectiva del usuario. Mucho menos trabajo para el worker.

En un sitio de contenido pequeño que realiza aproximadamente 33.000 solicitudes/día, la CPU mediana por solicitud se redujo de 668 ms a ~40 ms después de habilitar esto, una reducción de aproximadamente el 94%. El tiempo total de CPU facturado contra los $0.02 por millón de ms de CPU de Cloudflare pasó de ~22M ms/día a ~1.3M ms/día. La forma de la curva de costos en el panel de facturación cambió el mismo día que se desplegó.

Los ahorros escalan linealmente con el tráfico. Cuanto más concurrido sea el sitio, mayor será la brecha entre "dos viajes remotos de ida y vuelta por solicitud" y "una lectura local de la API de caché por solicitud".

Cuándo usarlo

Si tu configuración de OpenNext utiliza kvIncrementalCache con d1TagCache (la configuración recomendada por defecto para sitios de contenido en Cloudflare), activa withRegionalCache con bypassTagCacheOnCacheHit: true. Blogs, sitios de documentación, páginas de marketing y cargas de trabajo similares mayormente estáticas se benefician inmediatamente y la contrapartida de la obsolescencia es invisible.

Si estás ejecutando una aplicación donde la frescura importa en tiempo real (precios, inventario, chat), mantén bypassTagCacheOnCacheHit: false. Aún obtienes la capa de API de caché regional, lecturas de KV más rápidas, menor CPU por solicitud, sin la ventana de obsolescencia.

Es un diff de cinco líneas. El tipo de cambio que se paga solo el primer día.

Mantente Actualizado

Recibe las últimas publicaciones e ideas directamente en tu bandeja de entrada.

Unsubscribe anytime. No spam, ever.