Cloud CDN
Service 20

Cloud CDN

NetworkEdge

Cloud CDN caches content at Google's edge POPs — over 200 locations worldwide — so users get bytes from the closest one instead of round-tripping to the origin. The result is lower user-perceived latency and dramatically lower egress cost on cacheable content.

The key fact that catches people new to Cloud CDN: it is not a standalone service. Cloud CDN is a feature flag on an external Application Load Balancer's backend service. You do not deploy a "Cloud CDN endpoint"; you enable CDN on a backend service of an existing global Application Load Balancer. Internalize this and everything else makes sense.

CDN as a Load Balancer Feature

Cloud CDN binds to a backend service on a global external Application Load Balancer. Traffic arrives at the load balancer's anycast IP, hits the nearest Google POP, and either serves from cache or fetches from the backend behind the LB. The CDN layer adds caching to the load balancing path that already existed — you do not change DNS, you do not change the URL structure, you flip a setting. Regional LBs do not support Cloud CDN; only the global Application LB does.

Cache Modes

A backend service with CDN enabled runs in one of three cache modes:

  • USE_ORIGIN_HEADERS — respect the Cache-Control headers your origin returns; cache when the origin says it is cacheable, do not cache when it says it is not. The most principled choice when the origin is set up correctly.
  • CACHE_ALL_STATIC — cache static content (images, CSS, JS, fonts, video) automatically; pass through dynamic content. The safe default for a typical web application.
  • FORCE_CACHE_ALL — cache everything regardless of headers. Use only when the entire backend response is genuinely public and immutable. A single misuse — say, an authenticated API path mixed into the backend — serves one user's response to another.

Cache Key Composition

Default keyincludes query string
Tracking params fragment the cache. /p?id=1&utm_source=x and /p?id=1&utm_source=y become separate entries — hit rate collapses on the same content.
Tuned keystrip tracking params
One entry for the real content. Exclude utm_* and other irrelevant params from the cache key so identical responses share one cached object.

By default Cloud CDN keys cache entries on the request's host, path, and query string. If your application's response varies on additional inputs — Accept-Language, custom headers, a logged-in cookie — you must add those to the cache key configuration. The opposite mistake is also common: leaving the query string in the cache key when it carries irrelevant tracking parameters (utm_*, gclid) causes one canonical URL to occupy hundreds of cache slots. Strip query parameters that do not affect the response.

Signed URLs and Cookies

For paywalled or otherwise restricted content (video downloads, premium assets), Cloud CDN supports signed URLs and signed cookies. The application generates a time-limited signed URL; Cloud CDN validates the signature at the edge and serves the asset without consulting the origin. Without signed URLs, the origin handles every paywall check itself — defeating most of the CDN's value when traffic spikes.

Cache Invalidation and TTL Strategy

Cache invalidation by path is supported but quota-limited and not designed for high-frequency use. Treat invalidation as a fire-extinguisher mechanism for emergencies, not as the primary content-update path. Better: version your URLs (cache-busting filenames like main.a3f7c2d.js) and let old TTLs expire naturally. Set Cache-Control: max-age appropriately at the origin — long for immutable versioned assets, short for HTML that needs freshness.

Negative Caching

Negative caching stores error responses (404, 410, 5xx) at the edge for a short TTL. Without it, every 404 on a missing image hits the origin — which under attack or popular-but-missing-asset conditions can effectively DDoS your own backend. Enable negative caching with a short TTL (a few seconds to a minute) on all production backend services.

Common Mistakes
  • No CDN on public-facing apps with significant static or semi-static content — paying for origin egress and serving users slower than necessary.
  • FORCE_CACHE_ALL on a backend that also serves personalized or authenticated responses — one user's response gets served to another.
  • Cache key includes tracking query parameters (utm, gclid) — one canonical URL fragments into hundreds of cache entries, cache hit rate collapses.
  • Cache key excludes the dimension the response actually varies on (Accept-Language, a custom segmentation header) — wrong content served from cache.
  • Treating cache invalidation as the primary update mechanism — quota runs out, deploys block waiting for invalidations.
  • No signed URLs for paid content — every paywall check still hits the origin even though the CDN could serve the asset directly.
  • Negative caching disabled — origin gets hammered by 404s and 5xx requests that the edge could absorb.
Best Practices
  • Enable Cloud CDN on every global Application LB backend that serves cacheable content. The cost is near zero; the benefit is real.
  • Start with CACHE_ALL_STATIC unless you have explicit Cache-Control discipline at the origin.
  • Set Cache-Control: max-age explicitly at the origin: long for versioned immutable assets, short for HTML, no-store for personalized responses.
  • Strip tracking query parameters from the cache key. Add only headers and cookies the response actually varies on.
  • Use signed URLs or signed cookies for any paywalled, time-limited, or per-user assets.
  • Enable negative caching with a short TTL on every production backend service.
  • Version asset URLs (main.a3f7c2d.js) so deploys do not depend on cache invalidation.
Comparable services AWS CloudFront Azure Front Door + Azure CDN

Knowledge Check

How is Cloud CDN deployed in front of a workload?

  • As a standalone Cloud CDN endpoint with its own provisioned DNS hostname and anycast IP that clients resolve to directly
  • As a feature flag you enable on the backend service of a global external Application Load Balancer that already fronts the app
  • By installing a CDN module inside the GKE cluster or the VM that originates the content itself
  • By creating a CDN-specific Network Endpoint Group that sits in front of the origin backend service

What is the risk of FORCE_CACHE_ALL cache mode?

  • FORCE_CACHE_ALL silently bypasses signed-URL token validation at the edge and exposes paid, gated content to any anonymous client
  • It rapidly increases cache-invalidation quota consumption because every cached path must be re-validated against the origin on each request
  • Every response is cached regardless of headers; if any path serves authenticated or personalized responses, one user's response can be served to another
  • It disables negative caching of 404 and 410 responses by default, leaving the origin exposed to repeated floods of requests for objects that no longer exist

Why strip tracking query parameters (utm_*, gclid) from the Cloud CDN cache key?

  • Tracking parameters such as gclid and utm_source count as personal data under GDPR, so caching any URL that still contains them is itself a violation
  • They do not affect the response, but leaving them in the key fragments one canonical URL into hundreds of cache entries, collapsing cache hit rate
  • Tracking parameters break URL signing, so any paid content sitting behind a signed URL stops loading for the end user
  • Cloud CDN treats any request carrying utm or gclid parameters as uncacheable and bypasses the cache entirely as a built-in safety measure for tracked traffic

What is the purpose of signed URLs in Cloud CDN?

  • To rewrite the cache key for each visitor so that personalized responses can be cached safely at the edge and still served to the right user
  • To allow Cloud CDN to validate access at the edge and serve paid or time-limited content without the origin handling every paywall check
  • To enable and enforce encrypted HTTPS on the backend connection between Cloud CDN's edge POPs and the origin load balancer or storage bucket that holds the content
  • To trigger on-demand cache invalidation for protected paths without consuming any part of the project's per-minute invalidation quota at all

Why prefer versioned asset URLs (e.g. main.a3f7c2d.js) over relying on cache invalidation for deploys?

  • Versioned filenames reduce egress bandwidth costs because the hashed asset URL is compressed more aggressively at the edge before bytes leave Google's premium network
  • Cache invalidation is not supported on global external Application Load Balancer backends, so a hashed filename is the only way to refresh content there
  • Cache invalidation is quota-limited and was never designed for high-frequency use; versioned URLs let the old TTLs expire naturally, with no invalidation calls on any deploy
  • Cloud CDN refuses to cache any response larger than 1 MB unless the asset URL carries a version hash somewhere in its filename

You got correct