This episode covers caching and performance in SvelteKit: caching headers and revalidation, static generation, prerendering, streaming, edge caching and CDN integration, plus performance budgets and monitoring.

Performance is not just about code speed, but also about how smartly the application avoids repeating work. Episode 14 covers caching and performance in SvelteKit: caching headers, revalidation, prerendering, streaming, edge caching through a CDN, plus how to set and monitor performance budgets.
The key to caching is balancing data freshness against latency. Data that rarely changes can be cached for a long time; data that changes often needs revalidation. SvelteKit gives you granular control at the route and response level, so caching policy can be tuned per page.
After this episode, you can cut response times significantly by setting the right headers, choosing prerender where it makes sense, and keeping the site fast at scale.
One important point: caching is not a substitute for speed, it is a multiplier. Make sure the underlying code is efficient before leaning on the cache to cover weaknesses.
The Cache-Control header tells the browser and CDN how long a response may be reused. In a server load function, you can set it with setHeaders, available on the event.
export const load = async ({ setHeaders }) => {
const data = await ambilData();
setHeaders({
"Cache-Control": "public, max-age=300, stale-while-revalidate=60"
});
return { data };
};A value of max-age=300 means the response stays valid for five minutes. stale-while-revalidate=60 allows serving the stale response while reloading data in the background, so users never wait when the cache expires.
For responses cached by a CDN, add s-maxage or use the platform's revalidation mechanism such as x-sveltekit-cache. Every hosting platform has a different interface, so read its documentation. The principle is the same: decide how long the cache lives and how it is refreshed when data changes. As an example, Vercel provides caching settings in its dashboard, while Cloudflare is managed via the dashboard or npx wrangler pages project list to list your Pages projects.
Pages that do not depend on the request can be prerendered at build time. The result is a static HTML file served directly from a CDN without running the server — the lowest response time you can achieve.
export const prerender = true;Add this single line to +page.js or +layout.js. SvelteKit crawls the routes listed in entries and generates HTML for each. Make sure prerendered pages do not use APIs that are specific per request.
Streaming lets a page be sent before all data is ready. Critical sections render first, while slow sections like comments or recommendations fill in later. In SvelteKit, return a promise from the load function to enable this.
export const load = async ({ fetch, params }) => {
const artikel = await fetch(`/api/artikel/${params.id}`).then((r) => r.json());
return {
artikel,
komentar: fetch(`/api/artikel/${params.id}/komentar`).then((r) => r.json())
};
};SvelteKit wraps this promise so it keeps working during SSR and hydration. On the client, sections that are still pending are displayed with {#await}, and the whole process is transparent to developers.
Static assets such as images, fonts, and files in the static folder are best served from a CDN. Platforms like Vercel, Cloudflare Pages, and Netlify handle this automatically. For self-hosting, put a CDN in front of the server or upload assets to object storage connected to a CDN.
npm run build
ls -la build/clientAssets given a unique per-version hash can be cached indefinitely because their filename changes whenever the content changes. SvelteKit generates hashed asset names during the build. Set Cache-Control: public, max-age=31536000, immutable for these hashed assets at the CDN or server level.
Note that immutable is only safe for hashed assets. Using it on HTML pages would trap users on an old version, so keep the policy separate for static assets and dynamic documents.
A performance budget is a numeric limit that must not be exceeded: for example, total JavaScript under 200 KB, Largest Contentful Paint under 2.5 seconds, or fewer than 30 requests. A budget turns performance into an explicit decision, not a hope.
npm install -D lighthouse
npx lighthouse http://localhost:4173 --only-categories=performance --output=jsonA budget without monitoring is just a wish. Send Real User Monitoring data to a service like Sentry or Google Analytics, and compare it against the budget at every release. Integrate performance audits into CI so PRs that worsen the metrics are rejected before reaching production.
Start by monitoring the three core metrics — LCP, CLS, and INP — then expand as needed. All three can be tracked at no cost with the web-vitals library in client code.
Key takeaways:
Cache-Control with max-age and stale-while-revalidate controls caching.In the next episode we get into performance optimization: profiling with browser devtools and build analysis, minimizing bundle size and code splitting, optimizing hydration and client-side transitions, plus prefetching and resource hints.