Cloud CDN is a critical part of App Hosting 's support for your web app. Every request to your backend goes through Cloud CDN first. Content that is already cached in the CDN is served immediately back to the user, skipping a trip to the Cloud Run service running your web app's server code. You can learn more about the general benefits of CDNs at web.dev .
Though the basic Cloud CDN configuration is set by App Hosting and cannot be modified, there are a number of things you can do to optimize your caching in order to increase page load speeds, reduce billed uncached content, and minimize traffic to Cloud Run.
Cacheable content
Cloud CDN stores responses in cache if ALLof the following conditions are true:
-  The request is a GET 
-  The response has a status code of 200,203,204,206,300,301,302,307,308,404,405,410,421,451, or501.
-  The response has a Cache-Controlheader with amax-ageors-maxagedirective, or anExpiresheader with a timestamp in the future.
-  The response has an Ageheader or aCache-Controlheader with an explicitpublicdirective.
-  The response is less than or equal to 10 MiB in size. 
and NONEof the following are true:
-  The response has a Set-Cookieheader
-  The response has a Varyheader with a value other thanAccept,Accept-Encoding,Access-Control-Request-Headers,Access-Control-Request-Method,Origin,Sec-Fetch-Dest,Sec-Fetch-Mode,Sec-Fetch-Site,X-Goog-Allowed-Resources,X-Origin,RSC,Next-Router-State-Tree,Next-Router-Prefetch, orNext-Router-Segment-Prefetch.
-  The response has a Cache-Controlheader with theno-storeorprivatedirective.
-  The request has a Cache-Controlheader with ano-storedirective.
-  The request has an Authorizationheader, unless the response has an explicit cache control directive.
Customize behavior with cache control directives
Next.js
Next.js sets cache-control directives implicitly based on a number of
factors 
. However, you can
override these by manually setting the header 
in your next.config.js 
file. For example, to ensure a page is not
cached in Cloud CDN:
   
 /** @type {import('next').NextConfig} */ 
  
 const 
  
 nextConfig 
  
 = 
  
 { 
  
 headers 
 : 
  
 async 
  
 () 
  
 = 
>  
 [{ 
  
 source 
 : 
  
 "/YOUR_PRIVATE_PAGE" 
 , 
  
 headers 
 : 
  
 [{ 
  
 key 
 : 
  
 "Cache-Control" 
 , 
  
 value 
 : 
  
 "private" 
  
 }], 
  
 }], 
  
 }; 
 
 
Angular
Angular SSR does not set explicit cache-control directives out of the box. You can add your own by specifying cache-control headers in your server routes. For example, to allow Cloud CDN to cache all pages for an hour:
  import 
  
 { 
  
 RenderMode 
 , 
  
 ServerRoute 
  
 } 
  
 from 
  
 '@angular/ssr' 
 ; 
 export 
  
 const 
  
 serverRoutes 
 : 
  
 ServerRoute 
 [] 
  
 = 
  
 [ 
  
 { 
  
 path 
 : 
  
 '**' 
 , 
  
 renderMode 
 : 
  
 RenderMode 
 . 
 Prerender 
 , 
  
 headers 
 : 
  
 { 
  
 'Cache-Control' 
 : 
  
 'public, max-age=3600' 
 , 
  
 } 
  
 } 
 ]; 
 
 
Or to ensure a specific page will not be cached:
  import 
  
 { 
  
 RenderMode 
 , 
  
 ServerRoute 
  
 } 
  
 from 
  
 '@angular/ssr' 
 ; 
 export 
  
 const 
  
 serverRoutes 
 : 
  
 ServerRoute 
 [] 
  
 = 
  
 [ 
  
 // ... other routes 
  
 { 
  
 path 
 : 
  
 'YOUR_PRIVATE_PAGE' 
 , 
  
 renderMode 
 : 
  
 RenderMode 
 . 
 Server 
 , 
  
 headers 
 : 
  
 { 
  
 'Cache-Control' 
 : 
  
 'private' 
 , 
  
 } 
  
 } 
 ]; 
 
 
Respected directives
Firebase App Hosting 's Cloud CDN instance respects the following cache control directives:
| Directive | Request | Response | 
|---|---|---|
| no-store | When present in a request, the response will not be cached. | A response with no-storeisn't cached. | 
| no-cache | The no-cacherequest directive is ignored to prevent clients from potentially initiating or forcing revalidation to the origin. | A response with no-cacheis cached but must be revalidated with the origin before being served. | 
| public | N/A | This directive is not required for cacheability, but it is a best practice to include it for content that should be cached by proxies. | 
| private | N/A | A response with the privatedirective isn't cached by Cloud CDN, even if the response is otherwise considered cacheable. Clients (such as browsers) might still cache the result. Useno-storeto prevent all caching of responses. | 
| max-age=SECONDS | The max-agerequest directive is ignored. A cached response is returned as if this header was not included in the request. | A response with the max-agedirective is cached up to the defined SECONDS. | 
| s-maxage=SECONDS | N/A | A response with the s-maxagedirective is cached up to the defined SECONDS. If bothmax-ageands-maxageare present,s‑maxageis used by Cloud CDN. Responses with this directive aren't served stale.s-max-age(two hyphens) is not valid for the purposes of caching. | 
| max-stale=SECONDS | The max-stalerequest directive dictates the maximum staleness 
(in seconds) that the client is willing to accept. Cloud CDN honors this, and returns a stale cached response only if the staleness of the response is less than themax-staledirective. Otherwise, it revalidates before serving the request. | N/A | 
| stale-while-revalidate=SECONDS | N/A | A response with stale-while-revalidateis served to a client for up to SECONDS while revalidation takes place asynchronously. | 
| must-revalidate | N/A | A response with must-revalidateis revalidated with the origin server after it expires. Responses with this directive aren't served stale. | 
| proxy-revalidate | A response with proxy-revalidateis revalidated with the origin server after it expires. Responses with this directive aren't served stale. | |
| no-transform | N/A | No transforms are applied by Cloud CDN. | 
Measure cached and uncached traffic
The "Cloud CDN - Outgoing Bandwidth" graph in the Usagetab of the App Hosting console shows cached and uncached bytes served, and has a mark for each rollout. You can use this graph to measure the effectiveness of your cache optimization efforts.
You can also view the cache hit rate for specific routes in your web app with Route-based Monitoring .

