ADR-008: KV Cache voor Publieke Site (ISR Pattern)
Beslissing
Section titled “Beslissing”Cloudflare KV als edge-cache laag voor de publieke site. Public site leest uit KV (~1ms), valt terug naar Supabase bij miss (~80-150ms), en vult KV na succesvolle fallback (write-on-miss). KV wordt instant geïnvalideerd bij content-mutaties.
Context
Section titled “Context”De publieke site deed bij elke request 2-5 Supabase queries (~80-150ms per stuk). Met CDN edge cache (s-maxage=300) was de TTFB acceptabel, maar na cache expiry of purge moest elke bezoeker wachten op de database. Bij schaal naar 500+ sites wordt dit een bottleneck.
Alternatieven
Section titled “Alternatieven”| Optie | Voordeel | Nadeel |
|---|---|---|
| KV cache (gekozen) | ~1ms reads, instant invalidatie, geen infra overhead | KV eventual consistency (~60s cross-region) |
| Neon read replica | SQL-compatibel, geen applicatiewijziging | Migratierisico, hogere kosten ($69/mo) |
| Langere CDN TTL | Simpelst | Stale content tot 5-10 min na publicatie |
| Full static generation | Snelst | Hele site rebuilden bij 1 wijziging |
Architectuur
Section titled “Architectuur”Bezoeker → CDN (edge cache) → Astro SSR → KV (~1ms) │ miss? ▼ Supabase → response + KV vullen
Editor slaat op → API → Supabase write → KV delete (instant invalidatie) → CDN purge (bestaand)KV key schema:
| Key | Inhoud | TTL |
|---|---|---|
host:{hostname} | Site context (siteId, ownerId, siteSlug) | 24h |
site:{siteId} | Site config + menus + nav + logo | 24h |
page:{siteId}:{slug} | Page data (blocks, SEO, settings) | 24h |
brand-css:{siteId} | Pre-generated CSS string | 24h |
Invalidatie-triggers:
| Trigger | KV actie |
|---|---|
| Page opslaan/verwijderen | Delete page: + site: |
| Brand update/restore | Delete brand-css: |
| Menu/nav wijziging | Delete site: |
| Domein wijziging | Delete host: |
| Site soft-delete | Delete site: + host: entries |
| Pattern propagatie | Delete affected page: keys |
Gevolgen
Section titled “Gevolgen”- TTFB ~100ms → ~1-5ms voor 95%+ requests (KV hit)
- DB load -95% — Supabase alleen bij eerste bezoek na publicatie
- Instant freshness — KV wordt verwijderd vóór de response naar de editor teruggaat
- Graceful degradation — zonder KV binding (local dev) werkt alles via Supabase
- KV eventual consistency — cross-region propagatie ~60s (beter dan huidige 300s CDN)
- Geen
waitUntil()in Astro — write-on-miss isawait’ed (~10-20ms, alleen bij miss) - Nieuwe API endpoint —
POST /cache/invalidatevoor dashboard-side KV invalidatie - Gedeelde KV namespace —
BEAM_CACHEgebonden aan zowel API Worker als CF Pages