Hoe de regionale cache van OpenNext de CPU van Workers vermindert bij elke cache-hit
Next.js is gebouwd om standaard op Vercel te draaien. Het verwacht een bestandssysteem, een service voor afbeeldingsoptimalisatie en een specifiek runtime-model. Om Next.js elders te draaien, zoals op Cloudflare Workers, heb je een adapter nodig die die verwachtingen koppelt aan de primitieven van het doelplatform.
OpenNext is het open-source project dat precies dat doet. Het begon als een Next.js-adapter voor AWS Lambda en levert nu ook officiële adapters voor Cloudflare en Netlify. Het pakket waar we het hier over hebben is @opennextjs/cloudflare, waarmee je een Next.js-app kunt implementeren op Cloudflare Workers en de cachinglaag van Next.js koppelt aan de opslagprimitieven van Cloudflare.
Als je de aanbevolen Cloudflare-setup van OpenNext hebt gevolgd, koppelt je open-next.config.ts twee van die primitieven. Workers KV bevat de gecachte HTML van je vooraf gerenderde pagina's. D1 bevat de cache-tag metadata die revalidateTag() naar schrijft. (Standaard gebruikt defineCloudflareConfig() "dummy" no-op caches; KV en D1 zijn de aanbevolen vervangingen die je zelf koppelt.)
Zowel KV als D1 zijn externe services. Beide kosten echte CPU bij elk verzoek, zelfs als de pagina al dagen niet is gewijzigd. withRegionalCache is de wrapper die dat oplost.
Wat het is
withRegionalCache wordt meegeleverd met @opennextjs/cloudflare als een override die je om je bestaande incrementele cache-implementatie wikkelt. Het is een wijziging van één import, één 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,
});Het werkt op dezelfde manier rond r2IncrementalCache of staticAssetsIncrementalCache als die de backends zijn die je hebt gekozen. De wrapper is onafhankelijk van welke onderliggende cache je gebruikt.
Wat het doet
Twee dingen, beide de moeite waard om te begrijpen.
1. Een Workers Cache API-laag vóór KV
Het eerste gedrag is een regionale cachelaag die gebruikmaakt van caches.default, de Workers Cache API. De Cache API is lokaal voor elk Cloudflare-datacenter. Het is niet wereldwijd gerepliceerd, maar dat is juist het punt. Lezingen uit caches.default zijn in termen van CPU in wezen gratis en duren 1 tot 5 ms.
Dus wanneer een verzoek binnenkomt voor een gecachte pagina, controleert de worker eerst de Cache API van het lokale datacenter. Als de vermelding er is, retourneert het onmiddellijk. Zo niet, dan valt het terug op KV (een wereldwijde leesactie van ~30 tot 100 ms), vult het de lokale Cache API voor de volgende keer, en retourneert het de respons.
De optie mode: "long-lived" houdt regionale vermeldingen tot 30 minuten in stand, wat goed werkt voor ISR/SSG-pagina's.
2. Optionele D1 tag-cache bypass bij hits
Het tweede gedrag is optioneel: bypassTagCacheOnCacheHit: true.
Standaard vraagt elk verzoek naar een gecachte pagina ook D1 op om te controleren of een van de hervalidatietags van die pagina ongeldig is gemaakt. D1-leesacties duren ~30 tot 200 ms aan werkelijke tijd en verbruiken CPU voor het opzetten van queries en het parsen van resultaten.
Met de bypass ingeschakeld, slaat de worker die D1-retourreis over bij cache-hits. De afweging: als je revalidateTag() aanroept, kan de regionale cache de vorige versie van een pagina blijven serveren totdat de regionale vermelding verloopt. Voor inhoud die niet minuut-tot-minuut verandert, is dat onzichtbaar voor gebruikers.
Hoe het helpt
Zonder de wrapper ziet een typische "cache hit" er als volgt uit op de worker:
- Start het isolaat op.
- Query D1 voor tag-ongeldigmakingen op deze URL.
- Lees de gecachte HTML uit KV.
- Bouw de respons en retourneer.
Twee externe retourreizen en aanzienlijk CPU-werk, bij elk verzoek.
Met de wrapper:
- Start het isolaat op.
- Lees uit de lokale Cache API.
- Retourneer.
Hetzelfde resultaat vanuit het perspectief van de gebruiker. Veel minder werk voor de worker.
Op een kleine contentwebsite met ongeveer 33.000 verzoeken/dag, daalde de mediane CPU per verzoek van 668 ms naar ~40 ms na het inschakelen hiervan, een reductie van ongeveer 94%. De totale CPU-tijd die werd gefactureerd tegen Cloudflare's $0,02 per miljoen CPU-ms ging van ~22M ms/dag naar ~1,3M ms/dag. De vorm van de kostenlijn in het factureringsdashboard veranderde op dezelfde dag dat de implementatie werd uitgerold.
De besparingen schalen lineair met het verkeer. Hoe drukker de site, hoe groter het verschil tussen "twee externe retourreizen per verzoek" en "één lokale Cache API-leesactie per verzoek".
Wanneer te gebruiken
Als je OpenNext-configuratie kvIncrementalCache gebruikt met d1TagCache (de standaard aanbevolen setup voor contentwebsites op Cloudflare), schakel dan withRegionalCache in met bypassTagCacheOnCacheHit: true. Blogs, documentatiesites, marketingpagina's en vergelijkbare grotendeels statische workloads profiteren onmiddellijk en de afweging van veroudering is onzichtbaar.
Als je een app runt waarbij versheid in realtime belangrijk is (prijzen, inventaris, chat), houd bypassTagCacheOnCacheHit: false aan. Je krijgt nog steeds de regionale Cache API-laag, snellere KV-leesacties, minder CPU per verzoek, zonder het venster van veroudering.
Het is een diff van vijf regels. Het soort wijziging dat zichzelf op de eerste dag terugverdient.