vcl 4.1; # Minimal, safe Varnish config for a Next.js-style app. # - Cache static assets aggressively # - Avoid caching HTML/auth/api by default # - Preserve websockets / upgrade backend default { .host = "app"; .port = "3000"; } sub vcl_recv { # Health endpoint should always work. if (req.url == "/health") { return (pass); } # Websocket / Upgrade should not be cached. if (req.http.Upgrade ~ "(?i)websocket") { return (pipe); } # Only cache GET/HEAD. if (req.method != "GET" && req.method != "HEAD") { return (pass); } # If cookies are present, do not cache (safe default). if (req.http.Cookie) { return (pass); } # Never cache Next.js data requests (often personalized) unless you explicitly want to. if (req.url ~ "^/_next/data/") { return (pass); } # Cache immutable build assets. if (req.url ~ "^/_next/static/") { unset req.http.Cookie; return (hash); } # Cache common static files. if (req.url ~ "\.(?:css|js|mjs|map|png|jpg|jpeg|gif|webp|svg|ico|woff2?|ttf|otf)$") { unset req.http.Cookie; return (hash); } # Default: don't cache HTML. return (pass); } sub vcl_backend_response { # Cache immutable Next build assets for a long time. if (bereq.url ~ "^/_next/static/") { set beresp.ttl = 365d; set beresp.grace = 1h; set beresp.http.Cache-Control = "public, max-age=31536000, immutable"; unset beresp.http.Set-Cookie; return (deliver); } # Cache static files for 7 days (safe default). if (bereq.url ~ "\.(?:css|js|mjs|map|png|jpg|jpeg|gif|webp|svg|ico|woff2?|ttf|otf)$") { set beresp.ttl = 7d; set beresp.grace = 1h; if (!beresp.http.Cache-Control) { set beresp.http.Cache-Control = "public, max-age=604800"; } unset beresp.http.Set-Cookie; return (deliver); } # Everything else: don't cache by default. set beresp.ttl = 0s; set beresp.uncacheable = true; return (deliver); } sub vcl_deliver { # Helpful debug header; remove if you don't want this visible. if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } }