Bij Kinsta hebben we een obsessie voor snelheid: Onze diensten Applicatie Hosting, Database Hosting en Managed WordPress Hosting draaien allemaal op het snelste Premium Tier netwerk en C2 machines van het Google Cloud Platform en we vertrouwen op Cloudflare om ultieme snelheden te bieden aan onze tienduizenden klanten die hun content snel en veilig over de hele wereld willen verspreiden.

Door de jaren heen hebben we het een en ander geleerd over het gebruik van Cloudflare Workers en Workers KV om geoptimaliseerde cachingregels te bieden voor statische en dynamische content.

Begin 2023 hebben we de resources die gaan naar de cache van Cloudflare verdubbeld, waardoor caches beter reageren op wijzigingen in de configuratie aan de kant van de client, terwijl we het zware werk van het uitvoeren van feature updates overhevelen van onze backend admins naar Cloudflare Workers. Een belangrijk resultaat was een dramatische toename van het aandeel data van klanten dat met succes gecached kon worden, met een stijging van 56,3% tussen oktober 2022 en maart 2023.

Gegevens die een toename laten zien in het percentage succesvolle cache hits in de loop van de tijd.
Optimalisatie via Cloudflare Workers werd een sterkere focus in januari 2023.

Cloudflare Workers en Workers KV stellen ons in staat om programmatisch elk verzoek en antwoord aan te passen met minimale inspanning en lagere latency. We hoeven niet langer wijzigingen uit te rollen naar honderdduizenden containers wanneer we nieuwe features willen implementeren; we kunnen de feature repliceren of implementeren met Workers en deze overal implementeren met een paar commando’s en klikken, wat ons dagen werk en onderhoud bespaart.

Routing van verzoeken met Workers KV en Workers

Elk domein dat door Kinsta wordt gehost is een key en de waarde ervan bevat ten minste de kerninstellingen, zoals het IP en de poort van de origin en een unieke willekeurige ID. Met deze gegevens – eenvoudig beschikbaar in Workers KV – kunnen we Workers gebruiken om verzoeken te analyseren, te manipuleren en te routen naar het verwachte backend. We gebruiken Workers KV ook om optimalisatieopties voor klanten op te slaan, zoals Polish, Image Resizing en Auto Minify.

Om verzoeken naar custom IP’s en poorten te routen, gebruiken we resolveOverride, een Cloudflare-specifieke Request eigenschap. Hier is een voorbeeld:

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

// Override the backend
cf.resolveOverride = customBackend;

Maar hoewel Workers KV goed werkte om verzoeken te routen, merkten we al snel inconsistente responses in onze cache. Soms activeerde een klant Pools en door de één-minuut-cache van Workers KV kwamen er nieuwe verzoeken binnen voordat Workers KV de wijziging volledig had doorgevoerd, waardoor we niet-geoptimaliseerde assets in de cache hadden staan. Als dit gebeurde, moest de klant zijn cache weer handmatig wissen. Niet het ideale scenario. Klanten raakten gefrustreerd en wij verspilden API operaties en GCP bandbreedte door voortdurend caches op te ruimen.

Cache-keys zijn de sleutel

Omdat we altijd de KV data van de Workers van het domein lezen, realiseerden we ons dat we verzoeken konden routen en de cache-keys konden aanpassen door dingen toe te voegen zoals de ID van het domein en kenmerken die van invloed konden zijn op de asset, zoals Pools. Tegenwoordig is onze cache-key sterk aangepast om snel elke verandering van de klant in ons paneel of API door te voeren. Door de cache-keys aan te passen met de gegevens van Workers KV, hoeft niemand zich meer zorgen te maken over het wissen van de cache. Zodra Workers KV de veranderingen propageert, verandert ook de cache-key en vragen we een nieuwe asset op en cachen deze.

De eenvoudigste manier om de cache-key aan te passen is door er query params aan toe te voegen. Bijvoorbeeld:

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

Natuurlijk moet je de URL controleren op bestaande parameters om te bepalen welke connector je moet gebruiken – ? of & – en ervoor zorgen dat je een unieke identifier gebruikt.

Vervolgens kun je deze nieuwe cache sleutel gebruiken om de respons op te slaan met Cache API of Fetch – of beide.

Workers KV cache

Workers KV operaties zijn betaalbaar, maar de aantallen kunnen zich opstapelen als je dagelijks miljarden leesoperaties activeert.

Dankzij onze aanpassing van de cache-key realiseerden we ons dat we de Workers KV data konden cachen met Cache API, waardoor we op leesbewerkingen konden besparen en mogelijk de latency konden verlagen door meerdere Workers KV GET gerzoeken per bezoeker te vermijden. Omdat de gecachete respons nu gebaseerd is op de URL van het verzoek in combinatie met KV gegevens, hoeven we ons geen zorgen meer te maken over het cachen van verouderde content.

Grafiek met processtroom bij het cachen van Workers KV gegevens.
De processtroom met caching van Workers KV gegevens inbegrepen.
Grafiek met TTFB-reacties voor verschillende caching-scenario's.
Gemiddelde tijd tot de eerste byte in verschillende cachingscenario’s.

In tegenstelling tot veel applicaties kunnen we Workers KV echter niet voor langere perioden cachen. De klanten van Kinsta proberen voortdurend nieuwe features uit, wijzigen Pools en Auto Minify instellingen, sluiten soms pagina’s of extensies uit van de cache en willen hun wijzigingen zo snel mogelijk in productie zien.

Dat is toen we besloten om onze Workers KV data te microcachen – het cachen van dynamische of constant veranderde content voor een zeer korte periode, meestal minder dan 60 seconden.

Het is vrij eenvoudig om je eigen Workers KV cachinglogica te implementeren. Bijvoorbeeld:

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;
};

(Optioneel zou je de BetterKV van FlareUtils kunnen gebruiken.)

Bij Kinsta hebben we een cache TTL van 30 seconden geïmplementeerd voor Workers KV data, waardoor leesbewerkingen met ongeveer 80% afnemen.

Grafiek die de verandering in leesbewerkingen in de loop van de tijd laat zien.
Daling in leesbewerkingen na implementatie van een TTL van 30 seconden voor Workers KV datacache.

Meer informatie

Wil je meer weten over Workers en Workers KV? Bekijk de Cloudflare Workers KV developer documentatie of begin met een bezoek aan Cloudflare’s speciale Workers KV homepage.

Dit artikel is oorspronkelijk gepubliceerd op de website van 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.