Retour au Blog

Comment le cache régional d'OpenNext réduit le CPU des Workers à chaque succès de cache

2026-04-254 min read

Next.js est conçu pour fonctionner sur Vercel par défaut. Il s'attend à un système de fichiers, à un service d'optimisation d'images et à un modèle d'exécution particulier. Pour exécuter Next.js ailleurs, comme sur Cloudflare Workers, vous avez besoin d'un adaptateur qui fait le pont entre ces attentes et les primitives de la plateforme cible.

OpenNext est le projet open-source qui fait exactement cela. Il a commencé comme un adaptateur Next.js pour AWS Lambda et propose désormais des adaptateurs officiels pour Cloudflare et Netlify. Le package qui nous intéresse ici est @opennextjs/cloudflare, qui vous permet de déployer une application Next.js sur Cloudflare Workers et de connecter la couche de cache de Next.js aux primitives de stockage de Cloudflare.

Si vous avez suivi la configuration Cloudflare recommandée par OpenNext, votre open-next.config.ts connecte deux de ces primitives. Workers KV contient le HTML mis en cache de vos pages pré-rendues. D1 contient les métadonnées de cache-tag que revalidateTag() écrit. (Par défaut, defineCloudflareConfig() utilise des caches "dummy" sans effet ; KV et D1 sont les remplacements recommandés que vous connectez vous-même.)

KV et D1 sont tous deux des services distants. Tous deux coûtent du CPU réel à chaque requête, même lorsque la page n'a pas changé depuis des jours. withRegionalCache est l'enveloppe qui résout ce problème.

Ce que c'est

withRegionalCache est fourni avec @opennextjs/cloudflare comme une surcharge que vous appliquez autour de votre implémentation de cache incrémental existante. C'est un changement d'une seule importation et d'un seul enveloppement dans 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,
});

Cela fonctionne de la même manière avec r2IncrementalCache ou staticAssetsIncrementalCache si ce sont les backends que vous avez choisis. L'enveloppe est indépendante du cache sous-jacent que vous utilisez.

Ce que cela fait

Deux choses, toutes deux dignes d'intérêt.

1. Une couche Cache API de Workers devant KV

Le premier comportement est une couche de cache régionale utilisant caches.default, l'API Cache de Workers. L'API Cache est locale à chaque centre de données Cloudflare. Elle n'est pas répliquée globalement, mais c'est tout l'intérêt. Les lectures depuis caches.default sont essentiellement gratuites en termes de CPU et se terminent en 1 à 5 ms.

Ainsi, lorsqu'une requête arrive pour une page mise en cache, le worker vérifie d'abord l'API Cache du centre de données local. Si l'entrée s'y trouve, il la renvoie immédiatement. Sinon, il se rabat sur KV (une lecture globale d'environ 30 à 100 ms), peuple l'API Cache locale pour la prochaine fois, et renvoie la réponse.

L'option mode: "long-lived" maintient les entrées régionales pendant 30 minutes par défaut, ce qui fonctionne bien pour les pages ISR/SSG.

2. Contournement optionnel du cache de tags D1 lors des succès

Le deuxième comportement est optionnel : bypassTagCacheOnCacheHit: true.

Par défaut, chaque requête vers une page mise en cache interroge également D1 pour vérifier si l'un des tags de révalidation de cette page a été invalidé. Les lectures D1 prennent environ 30 à 200 ms de temps réel et consomment du CPU pour la configuration de la requête et l'analyse des résultats.

Avec le contournement activé, le worker ignore ce trajet D1 lors des succès de cache. Le compromis : si vous appelez revalidateTag(), le cache régional peut continuer à servir l'ancienne version d'une page jusqu'à l'expiration de son entrée régionale. Pour le contenu qui ne change pas d'une minute à l'autre, cela est invisible pour les utilisateurs.

Comment cela aide

Sans l'enveloppe, un "succès de cache" typique ressemble à ceci sur le worker :

  1. Réveil de l'isolat.
  2. Interrogation de D1 pour les invalidations de tags sur cette URL.
  3. Lecture du HTML mis en cache depuis KV.
  4. Construction de la réponse et renvoi.

Deux allers-retours distants et un travail CPU significatif, sur chaque requête.

Avec l'enveloppe :

  1. Réveil de l'isolat.
  2. Lecture depuis l'API Cache locale.
  3. Renvoi.

Même résultat du point de vue de l'utilisateur. Beaucoup moins de travail pour le worker.

Sur un petit site de contenu effectuant environ 33 000 requêtes/jour, le CPU médian par requête est passé de 668 ms à environ 40 ms après l'activation, soit une réduction d'environ 94 %. Le temps CPU total facturé sur les 0,02 $ par million de ms CPU de Cloudflare est passé d'environ 22 millions de ms/jour à environ 1,3 million de ms/jour. La forme de la courbe des coûts dans le tableau de bord de facturation a changé le jour même du déploiement.

Les économies augmentent linéairement avec le trafic. Plus le site est fréquenté, plus l'écart est grand entre "deux allers-retours distants par requête" et "une lecture locale de l'API Cache par requête".

Quand l'utiliser

Si votre configuration OpenNext utilise kvIncrementalCache avec d1TagCache (la configuration recommandée par défaut pour les sites de contenu sur Cloudflare), activez withRegionalCache avec bypassTagCacheOnCacheHit: true. Les blogs, les sites de documentation, les pages marketing et les charges de travail principalement statiques similaires en bénéficient immédiatement et le compromis de fraîcheur est invisible.

Si vous exécutez une application où la fraîcheur est importante en temps réel (tarifs, inventaire, chat), conservez bypassTagCacheOnCacheHit: false. Vous bénéficiez toujours de la couche API Cache régionale, de lectures KV plus rapides, d'un CPU par requête plus faible, sans la fenêtre d'obsolescence.

C'est une modification de cinq lignes. Le genre de changement qui se rentabilise dès le premier jour.

Restez Informé

Recevez les derniers articles et analyses directement dans votre boîte de réception.

Unsubscribe anytime. No spam, ever.