Skip to content

perf(onboarding-embed): cache the embed page at the Netlify edge - #1162

Merged
hturnbull93 merged 7 commits into
mainfrom
perf/cache-onboarding-embed
Sep 25, 2026
Merged

hturnbull93 merged 7 commits into
mainfrom
perf/cache-onboarding-embed

Conversation

@hturnbull93

@hturnbull93 hturnbull93 commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Why

The join embed on the UK site loaded slowly. /embed/onboarding-form is rendered on demand by a Netlify function and sent no cache headers (cache-status: "Netlify Edge"; fwd=miss), so each uncached hit paid a cold start. Measured: 4.1s on a cold hit, 0.15–0.4s warm. The recent university typeahead (#1159) isn't the cause: it adds a 12 KB JSON file and client-side filtering only.

What

A load in src/routes/embed/onboarding-form/+page.server.ts sets:

  • cache-control: public, max-age=0, s-maxage=300, stale-while-revalidate=86400 (Netlify's edge caches for 5 min; browsers still revalidate)
  • netlify-vary: query=locale|country|city|source|languages|bg

Netlify keys on the full query string by default, so unknown params (?x=1) would each create a cache entry and re-run the function. Listing the six params the page reads keeps the key to those. They live in CACHE_VARY_PARAMS, with a pointer comment in +page.svelte to keep the two in sync.

The rendered HTML has no per-visitor input: onboarding mode, Turnstile and the referrer-derived source are all resolved client-side, and nothing reads cookies or Accept-Language. The form POST action is unaffected. A deploy clears the cache.

Findings on the deploy preview

  • netlify-cdn-cache-control (with or without durable, s-maxage or max-age) gave no hits and never showed a Netlify Durable cache-status line. Cause: the site runs as Netlify Edge Functions (USE_EDGE_FUNCTIONS = true in svelte.config.js), where durable is unsupported. Plain s-maxage in cache-control did give hits (cache-status: hit; ttl=297), so that is what is used.
  • The cache is per edge node, so a request can still miss until each node has the page; hit rate climbs with traffic. On a quiet preview it was ~30% cold, rising as nodes warmed.
  • Unknown params shared the bare URL's entry (18/25 hits vs 7/25 when cold). Not a rigorous isolation test (one fixed junk value per run), so worth a glance on production.

Test plan

  • cache-control and netlify-vary present on the preview response
  • Repeat requests return cache-status: "Netlify Edge"; hit; ttl=…
  • Production, after deploy: hit ratio on /embed/onboarding-form?country=United%20Kingdom from the UK site
  • Form still submits from the embed

prettier and svelte-check pass (0 errors).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vver2Rh9E4SC5m6ttCpY7V

/embed/onboarding-form is rendered on demand by a Netlify function and had
no cache headers, so every uncached hit paid a cold start (~4s seen on the
UK site's iframe; warm hits take ~0.2s).

The HTML holds nothing per-visitor (mode, Turnstile and the referrer source
are resolved client-side), so serve it from Netlify's durable cache: 5 min
fresh, stale-while-revalidate for a day. Browsers still revalidate.

The cache key varies on exactly the query params the page reads (locale,
country, city, source, languages, bg) via Netlify-Vary, so unknown params
neither serve wrong HTML nor bust the cache.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vver2Rh9E4SC5m6ttCpY7V
@netlify

netlify Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for pauseai ready!

Name Link
🔨 Latest commit 04ebdde
🔍 Latest deploy log https://app.netlify.com/projects/pauseai/deploys/6ab60c447f18ca0008620d10
😎 Deploy Preview https://deploy-preview-1162--pauseai.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 69 (no change from production)
Accessibility: 91 (no change from production)
Best Practices: 100 (no change from production)
SEO: 82 (no change from production)
PWA: -
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

hturnbull93 and others added 6 commits September 25, 2026 06:24
…wasn't honoured

On the deploy preview netlify-cdn-cache-control left the response
stored but never fresh (age 0, fwd=miss on every request). Use s-maxage in
cache-control instead, as api/notion-image already does.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vver2Rh9E4SC5m6ttCpY7V
No measurable gain from durable on the deploy preview; the plain s-maxage
config gave verified cache hits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vver2Rh9E4SC5m6ttCpY7V
…apply

The site runs as Netlify Edge Functions, where durable has no effect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vver2Rh9E4SC5m6ttCpY7V
@hturnbull93
hturnbull93 merged commit 5d29566 into main Sep 25, 2026
9 checks passed
@hturnbull93
hturnbull93 deleted the perf/cache-onboarding-embed branch September 25, 2026 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant