Cloud CDN caches responses at Google’s edge locations, close to users. It is a setting on a backend service or backend bucket of an external Application Load Balancer.
flowchart LR U["User in Hanoi"] --> EDGE["Edge cache<br/>near the user"] EDGE -- "cache hit" --> U EDGE -- "cache miss" --> LB["External Application LB"] LB --> BB["Backend bucket<br/>gs://shop-static"] LB --> BS["Backend service web<br/>CDN on"] %% step U: A user requests /images/logo.png. %% step EDGE: If the edge cache holds a fresh copy, it answers immediately: a cache hit with low latency. %% step LB: On a miss, the request goes through the load balancer to the origin. %% step BB: Static files come from a Cloud Storage backend bucket. %% step BS: Dynamic pages come from the backend service; cacheable responses are stored at the edge for the next user.
Cache modes
| Mode | Behaviour |
|---|---|
CACHE_ALL_STATIC (default) |
Caches static content types (images, CSS, JS…) and anything with valid caching headers |
USE_ORIGIN_HEADERS |
Caches only what the origin marks cacheable with Cache-Control |
FORCE_CACHE_ALL |
Caches every successful response: only for fully public content, never for per-user pages |
Also configurable: default TTL (3600 s), max TTL, client TTL, negative caching for 404/5xx, and serve-while-stale.
Cache keys
By default the key is protocol + host + path + query string. Remove parts you do not need (for example tracking query parameters) to raise the cache hit ratio; include headers or cookies only if the response really varies by them.
Removing stale content
- Invalidation:
gcloud compute url-maps invalidate-cdn-cache web-map --path="/images/*". It is eventually consistent and rate-limited, so do not use it on every deploy. - Versioned URLs (
app.3f9c2.js) are better: new deploys use new names and old objects simply expire.
Private content
Signed URLs and signed cookies give time-limited access to cached content without making every user log in at the origin.
Watch
Monitor cache hit ratio, egress bytes and origin latency in the load balancer metrics. A low hit ratio usually means Cache-Control: private, cookies in responses, or too many unique query strings.
gcloud compute backend-services update web-backend --global --enable-cdn --cache-mode=CACHE_ALL_STATIC --default-ttl=3600
gcloud compute backend-buckets create static-bb --gcs-bucket-name=shop-static --enable-cdn
| Command | Meaning |
|---|---|
gcloud compute url-maps invalidate-cdn-cache web-map --path="/*" |
Invalidate everything (use sparingly) |
gcloud compute backend-services describe web-backend --global --format="value(enableCDN)" |
Is CDN on? |
Traps: FORCE_CACHE_ALL can serve one user’s page to another; responses with Set-Cookie or Cache-Control: private are not cached; Cloud CDN needs an external Application Load Balancer in front.