Torna al Blog

Come la cache regionale di OpenNext riduce la CPU dei Workers ad ogni cache hit

2026-04-254 min read

Next.js è progettato per funzionare su Vercel per impostazione predefinita. Si aspetta un filesystem, un servizio di ottimizzazione delle immagini e un modello di runtime specifico. Per eseguire Next.js altrove, come Cloudflare Workers, è necessario un adattatore che colleghi queste aspettative alle primitive della piattaforma di destinazione.

OpenNext è il progetto open-source che fa esattamente questo. È nato come adattatore Next.js per AWS Lambda e ora fornisce adattatori ufficiali anche per Cloudflare e Netlify. Il pacchetto che ci interessa qui è @opennextjs/cloudflare, che consente di distribuire un'app Next.js su Cloudflare Workers e collega il livello di cache di Next.js alle primitive di storage di Cloudflare.

Se hai seguito la configurazione Cloudflare consigliata da OpenNext, il tuo open-next.config.ts collega due di queste primitive. Workers KV memorizza l'HTML memorizzato nella cache delle tue pagine pre-renderizzate. D1 memorizza i metadati dei tag di cache che revalidateTag() scrive. (Per impostazione predefinita, defineCloudflareConfig() utilizza cache "dummy" no-op; KV e D1 sono i sostituti consigliati che colleghi tu stesso).

Sia KV che D1 sono servizi remoti. Entrambi consumano CPU reale ad ogni richiesta, anche quando la pagina non è cambiata da giorni. withRegionalCache è il wrapper che risolve questo problema.

Cos'è

withRegionalCache viene fornito con @opennextjs/cloudflare come override da applicare attorno alla tua attuale implementazione della cache incrementale. È una modifica di un'importazione e un wrapping in 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,
});

Funziona allo stesso modo con r2IncrementalCache o staticAssetsIncrementalCache se questi sono i backend che hai scelto. Il wrapper è indipendente dalla cache sottostante che utilizzi.

Cosa fa

Due cose, entrambe degne di nota.

1. Un livello API Cache Workers davanti a KV

Il primo comportamento è un livello di cache regionale che utilizza caches.default, l'API Cache di Workers. L'API Cache è locale a ogni data center di Cloudflare. Non è replicata a livello globale, ma questo è il punto. Le letture da caches.default sono essenzialmente gratuite in termini di CPU e terminano in 1-5 ms.

Quindi, quando arriva una richiesta per una pagina memorizzata nella cache, il worker controlla prima l'API Cache del data center locale. Se la voce è presente, la restituisce immediatamente. In caso contrario, ripiega su KV (una lettura globale di circa 30-100 ms), popola l'API Cache locale per la prossima volta e restituisce la risposta.

L'opzione mode: "long-lived" mantiene le voci regionali attive fino a 30 minuti per impostazione predefinita, il che funziona bene per le pagine ISR/SSG.

2. Bypass opzionale della cache dei tag D1 in caso di hit

Il secondo comportamento è opzionale: bypassTagCacheOnCacheHit: true.

Per impostazione predefinita, ogni richiesta a una pagina memorizzata nella cache interroga anche D1 per verificare se uno dei tag di revalidazione di quella pagina è stato invalidato. Le letture D1 richiedono circa 30-200 ms di tempo effettivo e consumano CPU per la configurazione della query e l'analisi dei risultati.

Con il bypass abilitato, il worker salta questo viaggio di andata e ritorno D1 in caso di hit della cache. Il compromesso: se chiami revalidateTag(), la cache regionale potrebbe continuare a servire la versione precedente di una pagina fino alla scadenza della sua voce regionale. Per i contenuti che non cambiano di minuto in minuto, questo è invisibile agli utenti.

Come aiuta

Senza il wrapper, un tipico "cache hit" appare così sul worker:

  1. Avvia l'isolato.
  2. Interroga D1 per le invalidazioni dei tag su questo URL.
  3. Leggi l'HTML memorizzato nella cache da KV.
  4. Costruisci la risposta e restituisci.

Due round trip remoti e un lavoro significativo di CPU, su ogni singola richiesta.

Con il wrapper:

  1. Avvia l'isolato.
  2. Leggi dall'API Cache locale.
  3. Restituisci.

Stesso risultato dal punto di vista dell'utente. Molto meno lavoro per il worker.

Su un piccolo sito di contenuti che gestisce circa 33.000 richieste/giorno, la CPU mediana per richiesta è scesa da 668 ms a circa 40 ms dopo l'attivazione, una riduzione di circa il 94%. Il tempo totale di CPU fatturato contro i $0,02 per milione di ms di CPU di Cloudflare è passato da circa 22 milioni di ms/giorno a circa 1,3 milioni di ms/giorno. La forma della curva dei costi nel dashboard di fatturazione è cambiata lo stesso giorno in cui è stata effettuata la distribuzione.

I risparmi scalano linearmente con il traffico. Più il sito è trafficato, maggiore è il divario tra "due round trip remoti per richiesta" e "una lettura locale dell'API Cache per richiesta".

Quando usarlo

Se la tua configurazione OpenNext utilizza kvIncrementalCache con d1TagCache (la configurazione consigliata predefinita per i siti di contenuti su Cloudflare), attiva withRegionalCache con bypassTagCacheOnCacheHit: true. Blog, siti di documentazione, pagine di marketing e carichi di lavoro prevalentemente statici simili beneficiano immediatamente e il compromesso sulla freschezza è invisibile.

Se stai eseguendo un'app in cui la freschezza è importante in tempo reale (prezzi, inventario, chat), mantieni bypassTagCacheOnCacheHit: false. Ottieni comunque il livello dell'API Cache regionale, letture KV più veloci, meno CPU per richiesta, senza la finestra di obsolescenza.

È una modifica di cinque righe. Il tipo di cambiamento che si ripaga il primo giorno.

Rimani Aggiornato

Ricevi gli ultimi articoli e approfondimenti direttamente nella tua casella di posta.

Unsubscribe anytime. No spam, ever.