Cloud CDN¶
Overview¶
Cloud CDN (Content Delivery Network) uses Google's globally distributed edge points of presence to cache HTTP(S) load-balanced content close to users, reducing latency and improving performance.
Table of Contents¶
CDN Fundamentals¶
How Cloud CDN Works¶
┌────────────────────────────────────────────────────────┐
│ Cloud CDN Architecture │
└────────────────────────────────────────────────────────┘
User (Tokyo)
│
├─→ Request: example.com/image.jpg
│ └─→ Nearest Edge Location (Tokyo)
│ ├─ Cache HIT → Return cached content ✓
│ └─ Cache MISS → Fetch from origin
│ └─→ Backend (us-central1)
│ └─→ Cache at edge
│ └─→ Return to user
│
└─→ Subsequent requests served from cache
Benefits:
├─ Reduced latency
├─ Lower bandwidth costs
├─ Reduced load on origin
└─ Improved user experience
Key Features¶
features:
- Global edge network (200+ locations)
- Automatic caching
- Cache invalidation
- Signed URLs/Cookies
- Custom cache keys
- Negative caching
- Compression
Enabling Cloud CDN¶
Enable on Backend Service¶
# Enable Cloud CDN on existing backend
gcloud compute backend-services update web-backend \
--enable-cdn \
--global
# Disable Cloud CDN
gcloud compute backend-services update web-backend \
--no-enable-cdn \
--global
Terraform¶
# Backend service with Cloud CDN
resource "google_compute_backend_service" "web" {
name = "web-backend"
protocol = "HTTP"
health_checks = [google_compute_health_check.web.id]
port_name = "http"
backend {
group = google_compute_instance_group_manager.web.instance_group
}
# Enable Cloud CDN
enable_cdn = true
cdn_policy {
cache_mode = "CACHE_ALL_STATIC"
default_ttl = 3600
max_ttl = 86400
client_ttl = 3600
negative_caching = true
serve_while_stale = 86400
negative_caching_policy {
code = 404
ttl = 120
}
negative_caching_policy {
code = 500
ttl = 60
}
cache_key_policy {
include_host = true
include_protocol = true
include_query_string = false
query_string_whitelist = ["id", "page"]
}
}
}
Cache Configuration¶
Cache Modes¶
# CACHE_ALL_STATIC (default)
cache_all_static:
description: "Cache static content automatically"
caches:
- Images (jpg, png, gif, webp)
- CSS and JavaScript
- Fonts
- Videos
use_case: "Most web applications"
# USE_ORIGIN_HEADERS
use_origin_headers:
description: "Respect Cache-Control headers from origin"
behavior: "Cache based on origin headers"
use_case: "Fine-grained control"
# FORCE_CACHE_ALL
force_cache_all:
description: "Cache all content regardless of headers"
behavior: "Override origin headers"
use_case: "Maximum caching"
TTL Configuration¶
resource "google_compute_backend_service" "web" {
name = "web-backend"
enable_cdn = true
cdn_policy {
cache_mode = "CACHE_ALL_STATIC"
# Default TTL (if origin doesn't specify)
default_ttl = 3600 # 1 hour
# Maximum TTL (cap for Cache-Control: max-age)
max_ttl = 86400 # 24 hours
# Client TTL (sent to browser)
client_ttl = 3600 # 1 hour
# Serve stale content while revalidating
serve_while_stale = 86400 # 24 hours
}
}
Cache Key Policy¶
resource "google_compute_backend_service" "web" {
name = "web-backend"
enable_cdn = true
cdn_policy {
cache_key_policy {
# Include in cache key
include_host = true
include_protocol = true
include_query_string = false
# Whitelist specific query parameters
query_string_whitelist = ["id", "page", "sort"]
# Or blacklist parameters
# query_string_blacklist = ["utm_source", "utm_medium"]
# Include headers in cache key
include_http_headers = ["Accept-Language"]
}
}
}
Negative Caching¶
resource "google_compute_backend_service" "web" {
name = "web-backend"
enable_cdn = true
cdn_policy {
negative_caching = true
# Cache 404 errors for 2 minutes
negative_caching_policy {
code = 404
ttl = 120
}
# Cache 500 errors for 1 minute
negative_caching_policy {
code = 500
ttl = 60
}
# Cache 502/503 errors for 30 seconds
negative_caching_policy {
code = 502
ttl = 30
}
}
}
Cache Invalidation¶
Invalidate Cache¶
# Invalidate all cached content
gcloud compute url-maps invalidate-cdn-cache web-map \
--path="/*" \
--async
# Invalidate specific path
gcloud compute url-maps invalidate-cdn-cache web-map \
--path="/images/*" \
--async
# Invalidate specific file
gcloud compute url-maps invalidate-cdn-cache web-map \
--path="/style.css" \
--async
# Invalidate multiple paths
gcloud compute url-maps invalidate-cdn-cache web-map \
--path="/images/*" \
--path="/css/*" \
--path="/js/*" \
--async
Terraform¶
# Trigger cache invalidation
resource "null_resource" "invalidate_cache" {
triggers = {
# Invalidate when deployment changes
deployment_id = var.deployment_id
}
provisioner "local-exec" {
command = <<-EOT
gcloud compute url-maps invalidate-cdn-cache ${google_compute_url_map.web.name} \
--path="/*" \
--async
EOT
}
depends_on = [google_compute_backend_service.web]
}
Python¶
# Invalidate cache programmatically
from google.cloud import compute_v1
def invalidate_cdn_cache(project_id, url_map_name, paths):
"""
Invalidate CDN cache for specified paths
"""
client = compute_v1.UrlMapsClient()
request = compute_v1.InvalidateCacheUrlMapRequest(
project=project_id,
url_map=url_map_name,
cache_invalidation_rule_resource=compute_v1.CacheInvalidationRule(
path=paths[0] if len(paths) == 1 else None,
paths=paths if len(paths) > 1 else None
)
)
operation = client.invalidate_cache(request=request)
print(f"Cache invalidation started: {operation.name}")
return operation
# Usage
invalidate_cdn_cache(
"my-project",
"web-map",
["/images/*", "/css/*", "/js/*"]
)
Best Practices¶
1. Use Appropriate Cache Modes¶
# For static websites
resource "google_compute_backend_service" "static" {
name = "static-backend"
enable_cdn = true
cdn_policy {
cache_mode = "CACHE_ALL_STATIC"
default_ttl = 86400 # 24 hours for static content
max_ttl = 604800 # 7 days
}
}
# For dynamic content with cache headers
resource "google_compute_backend_service" "dynamic" {
name = "dynamic-backend"
enable_cdn = true
cdn_policy {
cache_mode = "USE_ORIGIN_HEADERS"
}
}
2. Configure Cache Keys Properly¶
resource "google_compute_backend_service" "web" {
name = "web-backend"
enable_cdn = true
cdn_policy {
cache_key_policy {
include_host = true
include_protocol = true
include_query_string = false
# Only cache based on important parameters
query_string_whitelist = ["id", "page"]
# Ignore tracking parameters
# This improves cache hit ratio
}
}
}
3. Set Appropriate TTLs¶
# TTL guidelines
static_assets:
type: "Images, CSS, JS, fonts"
ttl: "86400 (24 hours) to 604800 (7 days)"
reason: "Rarely change"
html_pages:
type: "HTML content"
ttl: "300 (5 minutes) to 3600 (1 hour)"
reason: "May update frequently"
api_responses:
type: "API data"
ttl: "60 (1 minute) to 300 (5 minutes)"
reason: "Dynamic data"
error_pages:
type: "404, 500 errors"
ttl: "60 (1 minute) to 120 (2 minutes)"
reason: "May be temporary"
4. Use Compression¶
resource "google_compute_backend_service" "web" {
name = "web-backend"
enable_cdn = true
cdn_policy {
cache_mode = "CACHE_ALL_STATIC"
# Enable compression
compression_mode = "AUTOMATIC"
}
}
5. Monitor Cache Performance¶
# Monitor CDN metrics
from google.cloud import monitoring_v3
def monitor_cdn_performance(project_id):
"""
Monitor Cloud CDN cache hit ratio
"""
client = monitoring_v3.MetricServiceClient()
# Query cache hit ratio
interval = monitoring_v3.TimeInterval({
"end_time": {"seconds": int(time.time())},
"start_time": {"seconds": int(time.time()) - 3600},
})
results = client.list_time_series(
request={
"name": f"projects/{project_id}",
"filter": 'metric.type="loadbalancing.googleapis.com/https/backend_request_count"',
"interval": interval,
}
)
for result in results:
cache_hit = result.metric.labels.get('cache_result') == 'HIT'
print(f"Cache Hit: {cache_hit}")
monitor_cdn_performance("my-project")
Summary¶
Cloud CDN provides: - Global content delivery - Automatic caching - Reduced latency - Lower bandwidth costs - Improved performance
Quick Reference¶
# Enable CDN
gcloud compute backend-services update BACKEND \
--enable-cdn --global
# Invalidate cache
gcloud compute url-maps invalidate-cdn-cache URL_MAP \
--path="/*" --async
# Disable CDN
gcloud compute backend-services update BACKEND \
--no-enable-cdn --global
Next Steps¶
- Load Balancing - Traffic distribution
- Cloud DNS - DNS management
- Network Security - Security features
Last Updated: March 2026