CloudBrum
CloudBrum · Cloud decision-support platform
Google Cloud Networking

Cloud CDNLast reviewedReading time~12 minLevelBeginner to advanced

Google Cloud · Networking · Edge caching on the external Application Load Balancer

Cloud CDN is a switch you turn on for a backend of Google’s external Application Load Balancer, and from then on responses are cached in Google’s edge locations. There is no separate network to set up: the same front end that terminates TLS and routes by URL also decides whether an answer can come from the cache. That is a strength, because one set of rules covers routing, caching and protection with Cloud Armor, and a weakness, because you need a load balancer first, and its charges come with it. The settings that matter are the cache mode, the cache key and how long things live.

On this page (17 sections)

    Mind map: Cloud CDN at a glance

    Cloud CDN mind map Cloud CDN at a glance: Where it runs: External Application LB, Backend service, Backend bucket; Origins: Cloud Storage, VMs and NEGs, Cloud Run, external origins; Cache modes: USE_ORIGIN_HEADERS, CACHE_ALL_STATIC, FORCE_CACHE_ALL; Cache key: Host and protocol, Query strings, Named headers, cookies; Freshness: TTLs, Invalidation, Serve while stale; Private content: Signed URLs, Signed cookies, Key rotation; Protection: Cloud Armor, TLS on the load balancer, Service Extensions; Pricing: Cache egress, Cache fill, lookups, Load balancer charges. Cloud CDN at a glance Edge caching on Google Cloud: the main building blocks and decisions CloudBrum Cloud decision-support platform CloudBrum External Application LB Backend service Backend bucket Where it runs Cloud Storage VMs and NEGs Cloud Run, external origins Origins USE_ORIGIN_HEADERS CACHE_ALL_STATIC FORCE_CACHE_ALL Cache modes Host and protocol Query strings Named headers, cookies Cache key TTLs Invalidation Serve while stale Freshness Signed URLs Signed cookies Key rotation Private content Cloud Armor TLS on the load balancer Service Extensions Protection Cache egress Cache fill, lookups Load balancer charges Pricing Cloud CDN17-point analysis CloudBrum· 17-point cloud service analysis cloudbrum.com
    CloudBrum Cloud CDN at a glance · 17-point analysis Where it runs External Application LB Backend service Backend bucket Origins Cloud Storage VMs and NEGs Cloud Run, external origins Cache modes USE_ORIGIN_HEADERS CACHE_ALL_STATIC FORCE_CACHE_ALL Cache key Host and protocol Query strings Named headers, cookies Freshness TTLs Invalidation Serve while stale Private content Signed URLs Signed cookies Key rotation Protection Cloud Armor TLS on the load balancer Service Extensions Pricing Cache egress Cache fill, lookups Load balancer charges CloudBrum · cloudbrum.com

    Free to share. The downloaded image includes the CloudBrum link.

    Key features (summary)

    • A setting on the load balancerCloud CDN is enabled per backend on an external Application Load Balancer. Requests that hit the cache are served at the edge and never reach the load balancer’s backends, and misses go on to the origin as usual.
    • Many kinds of originA Cloud Storage bucket through a backend bucket, instance groups, zonal and serverless network endpoint groups such as Cloud Run, and external servers reached through an internet NEG.
    • Three cache modesUSE_ORIGIN_HEADERS caches only what the origin marks as cacheable. CACHE_ALL_STATIC also caches ordinary static content that has no headers. FORCE_CACHE_ALL caches everything successful, including responses that say private.
    • A cache key you controlBy default the key includes the protocol, host and full URL. You can drop the protocol or the query string, keep only named parameters, and add headers or cookies on backend services.
    • TTLs and stale answersSet a default, a client and a maximum TTL, cache errors briefly with negative caching, and let the edge serve a stale object for a while when the origin is slow or down.
    • Signed URLs and cookiesPrivate content can be served from the cache when the request carries a signature made with a key that you hold, with an expiry time. Keys can be rotated without downtime.
    • Protection at the edgeCloud Armor security policies sit in front of cached and uncached traffic alike. The load balancer terminates TLS with Google-managed or your own certificates.
    • Media CDN for the heavy casesCloud CDN suits websites and APIs. Media CDN is the separate product, on YouTube’s delivery infrastructure, for very large streaming and download workloads.

    Basic concepts

    External Application Load Balancer
    Google’s layer 7 load balancer with a single global address. Cloud CDN is an option on its backends.
    Backend service and backend bucket
    A backend service points at servers (instance groups or endpoint groups). A backend bucket points at a Cloud Storage bucket. Either can have Cloud CDN switched on.
    Cache mode
    Decides what Cloud CDN caches: only what the origin marks cacheable, also plain static content, or everything successful.
    Cache key
    What makes two requests the same cached object: protocol, host, path and, optionally, query string parameters, headers and cookies.
    TTL (default, client, max)
    The default TTL applies when the origin sends none. The client TTL caps what browsers are told. The maximum TTL caps how long the edge keeps an object, whatever the origin says.
    Negative caching
    Caches error responses such as 404 for a short time, so a missing file doesn’t hit the origin on every request.
    Serve while stale
    Lets the edge return an expired object for a set time while it refreshes it from the origin.
    Invalidation
    A request that removes a path or a path prefix from all caches. It takes a few minutes and is meant for exceptions.
    Signed URL and signed cookie
    A request carrying an expiry, a key name and a signature that Cloud CDN checks against the keys on the backend.
    Internet NEG
    A group that points to an external host name, so Cloud CDN and the load balancer can front a server outside Google Cloud.
    Cache fill
    The traffic from the origin into the cache when an object isn’t there yet. It is billed separately from cache egress.
    Custom response headers
    Headers the load balancer adds to responses, including variables such as the cache status, which makes caching visible to testers.
    Media CDN
    A separate Google Cloud product for large-scale video and downloads, with its own configuration and pricing.

    How to create & configure it

    Serve a static site from a bucket through Cloud CDN with gcloud

    1. Check that Cloud CDN fitsIt needs an external Application Load Balancer in front of the backend, so the site pays for the load balancer too. Plain TCP traffic or very large video are better served elsewhere.
    2. Put the files in a bucketCreate a bucket near your users, upload the site, and set a sensible Cache-Control header on the objects. Public content must be readable by the load balancer’s path.
    3. Create a backend bucket with CDN onPick a cache mode, set the default, client and maximum TTL, and turn on negative caching.
    4. Build the load balancerReserve a global address, create a URL map, a Google-managed certificate for your domain, an HTTPS proxy and a forwarding rule.
    5. Point DNS at the addressAdd an A record for your domain. The managed certificate becomes active once DNS points at the address, which can take a while.
    6. Make caching visibleAdd a custom response header with the cache status variable, so you can see hit and miss in a browser or with curl.
    7. Version your filesPut a hash in file names, so a release needs no invalidation. Invalidate only entry pages.
    8. Protect and tuneAttach a Cloud Armor policy, review the cache key, and consider signed URLs for private content.
    9. Watch the hit ratio and the billUse the load balancer logs and metrics to see cache hits, and review cache egress, cache fill and lookup charges.

    Tip: Cloud CDN can add the cache status to responses. With a custom response header that uses the {cdn_cache_status} variable, a quick curl -I tells you whether an answer came from the cache. See the code references for the same setup as Terraform.

    Common issues after configuration

    SymptomLikely causeWhat to check / fix
    Nothing is cached, and the hit ratio stays at zeroThe mode is USE_ORIGIN_HEADERS and the origin sends no cache headers, the response varies with a header that makes every request unique, or the request is not cacheable (for example a POST)Set Cache-Control at the origin, or use CACHE_ALL_STATIC for static content, and check the Vary header.
    Users still see the old version after a releaseThe edge keeps the object until its TTL endsInvalidate the changed paths, or use hashed file names and short TTLs for HTML.
    Private pages were served to the wrong personFORCE_CACHE_ALL ignores private and no-store, so a personalised response was cachedUse FORCE_CACHE_ALL only for content that is the same for everyone, and keep personalised paths on another backend.
    Hit ratio is low because the same file is cached many timesQuery strings or the protocol are in the cache key, so tracking parameters create separate objectsExclude the protocol and the query string, or keep only the parameters that change the response.
    A backend bucket answers 403The objects aren’t readable by the path Cloud CDN uses, or the bucket is private and no signing key or service account access is set upMake the content publicly readable, or keep it private and grant the Cloud CDN service account read access and use signed URLs.
    A signed URL returns 403The key name or the secret is wrong, the expiry has passed, or the URL was changed after signingCheck the key on the backend, sign the exact URL, use a UTC timestamp and a URL-safe base64 key.
    The managed certificate stays in provisioningDNS doesn’t point at the load balancer’s address, or the domain is also served by something elseCreate the A record for the forwarding rule’s address and wait. Check for conflicting records.
    HTTP requests aren’t redirected to HTTPSThe HTTPS proxy only listens on 443, and no HTTP front end existsA second forwarding rule on port 80 points at a URL map that only redirects to HTTPS.
    A cache miss is very slowThe origin is far from the edge location that fetched it, or is slow to respondMove the origin closer to the main audience, raise TTLs so misses are rarer, and use serve-while-stale.
    Invalidation takes a long time or seems ignoredInvalidations take minutes to spread, and a path with the wrong form, host or trailing wildcard misses the objectsUse the exact path or a single trailing *, give the host if you serve several, and wait for the operation to finish.
    The bill is higher than expectedCache egress, cache fill and lookup requests are billed, along with the load balancer’s forwarding rules and data processingRaise the hit ratio, compress responses, merge forwarding rules and compare the charges by SKU.

    Use cases: when and where to use it

    Good fit

    • Websites and single-page apps hosted in Cloud Storage, Cloud Run or on virtual machines
    • Applications that already use, or need, an external Application Load Balancer
    • Static assets, downloads and API answers that can be cached for a short time
    • Sites that want caching, TLS, URL routing and Cloud Armor in one front end
    • Content served from servers outside Google Cloud, through an internet NEG
    • Private downloads that use signed URLs with expiry times

    Consider something else

    • Very large video and download delivery → Media CDN
    • Distributing traffic across backends, with or without caching → Cloud Load Balancing
    • Hosting the files themselves → Cloud Storage
    • A fully managed web app with its own front end → Cloud Run
    • DNS records and routing policies → Cloud DNS
    • The same job on other clouds → compare Amazon CloudFront and Azure Front Door

    Pros: why consider it?

    Why teams choose it

    • Caching sits in the same front end as routing, TLS and protection
    • No separate CDN account, network or certificate setup
    • Cache hits skip the load balancer’s backends, so origin load falls
    • Three cache modes and a flexible cache key
    • Signed URLs and cookies for private content
    • Works with origins outside Google Cloud through an internet NEG

    Trade-offs to weigh

    • It needs an external Application Load Balancer, whose charges apply on top
    • There is no standalone CDN: the load balancer is the entry point
    • Invalidation is slow and meant for exceptions
    • FORCE_CACHE_ALL can cache private data if used carelessly
    • Fewer edge-compute options than some CDNs, with logic mostly in the load balancer’s URL map and extensions
    • Billing has several parts: egress, cache fill, lookups and the load balancer

    Common threats, vulnerabilities & risks

    RiskSeverityWhy it mattersMitigation
    FORCE_CACHE_ALL on personalised contentHighResponses marked private or no-store are cached anyway, and may be served to another visitor.Use it only for identical-for-everyone content, and route personalised paths to a backend without CDN.
    A public bucket holding private filesHighAnyone who finds the URL can fetch the object directly, even without the CDN.Use signed URLs with a private bucket, and grant read access only to the Cloud CDN service account.
    Signing keys left in code or logsHighA leaked key lets anyone create valid signed URLs until it is removed.Keep keys in Secret Manager, rotate them on a schedule and remove the old key after clients move.
    Origins open to the internetMediumAttackers can hit the origin directly, past Cloud Armor and the cache.Allow only the load balancer and health check ranges on the backend, and keep origin addresses private.
    Long TTLs on pages that changeMediumA mistake stays in the cache for the whole TTL.Keep HTML TTLs short, use hashed assets, and have a documented invalidation step.
    Wide cache keysMediumCookies or headers in the key fragment the cache and slow every visitor.Include only what changes the response.
    No Cloud Armor policyMediumBots and floods can push up egress charges and load.Attach a policy with rate limits and managed rules, and set a budget alert.
    Unreviewed load balancer changesLow–MedA change to the URL map or a backend can disable caching for a whole site.Keep the load balancer in code, review changes and watch the hit ratio after each.
    Origin outside Google Cloud with no limitsLow–MedCache misses can flood an external origin.Raise TTLs, use serve-while-stale and rate-limit the origin.

    Performance optimisation

    • Set long TTLs on hashed assets and short ones on HTML, so most requests are answered at the edge.
    • Keep the cache key small: drop the protocol and the query string unless they change the response.
    • Use CACHE_ALL_STATIC for sites whose origin doesn’t send good headers, and fix the headers when you can.
    • Turn on compression at the origin or load balancer for text, so responses are smaller.
    • Use serve while stale and negative caching to absorb origin slowness and repeated misses.
    • Place the origin near most users, since the first fetch for each edge location travels to it.
    • Use HTTP/3 and TLS 1.3 on the load balancer, which clients negotiate automatically.
    • Warm up important pages after a release by requesting them once, rather than letting the first visitors take the miss.

    Reduce monthly cost

    FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Cloud CDN.

    • Raise the cache hit ratio: cache egress is cheaper than the load balancer’s data processing, and fills are paid once per object.
    • Compress responses and size images, since cache egress is billed per GiB.
    • Use versioned file names instead of invalidations.
    • Reduce cache lookups by combining small files and removing needless requests, such as repeated polls.
    • Keep forwarding rules to what you need, since each one has an hourly charge.
    • Choose the region of the bucket and origin with care, because cache fill follows origin location.
    • Use Cloud Armor rate limits to stop abusive traffic that would raise egress.
    • Check whether Media CDN is cheaper for very large download or streaming workloads.
    • Review logs for requests that can never be cached, and fix or move them.
    • Add a budget alert and review the SKUs on the invoice every month.

    Figures here come from Google's pricing page and published guides, read in October 2026. Regional rates vary and a few sources disagree, so check the live page (see Pricing).

    Security optimisation

    • Use signed URLs or cookies for private content, short expiry times and rotated keys kept in Secret Manager.
    • Keep buckets private where you can, and give the Cloud CDN service account read access instead of making objects public.
    • Attach Cloud Armor policies for rate limits, geographic rules and managed protection.
    • Terminate TLS on the load balancer with a modern SSL policy and a minimum TLS version.
    • Allow only the load balancer and health check ranges to reach backends.
    • Use FORCE_CACHE_ALL only for content that is the same for every visitor.
    • Turn on request logging for the load balancer and send logs to a restricted bucket or Log Analytics.
    • Restrict who can change load balancers, backends and cache settings with IAM, and alert on changes.
    • Redirect HTTP to HTTPS with a separate front end on port 80.
    • Review Security Command Center findings for the project and its load balancers.

    Governance & compliance

    Guardrails

    • A shared Terraform module for load balancers that sets CDN, cache mode, TTLs, a Cloud Armor policy, logging and labels
    • An organisation policy and IAM review that limits who may change load balancers and make buckets public
    • A naming standard for backends and URL maps, with the cache mode and the reason for it noted on each backend
    • A release checklist covering hashed assets, HTML TTLs and the invalidation of entry pages

    Continuous checks (Cloud Asset Inventory, Security Command Center and your own scripts)

    • A scheduled script that lists backends with FORCE_CACHE_ALL, CDN switched off or a wide cache key (the C# tab does this)
    • Security Command Center and organisation policy findings for public buckets and load balancers
    • Alerts on the cache hit ratio, 5xx rate and backend latency
    • An audit-log alert for changes to backends, URL maps and signed URL keys
    • A monthly report of cost by SKU for the load balancer and Cloud CDN

    Cloud Audit Logs record who changed load balancers and backends, Cloud Asset Inventory keeps the configuration history, Security Command Center reports posture, and Google’s compliance reports manager holds certifications. Google runs the edge and the load balancer. Cache settings, signing keys, origin protection and what is cached are yours.

    Reduce carbon footprint

    • A higher cache hit ratio keeps cache fill and origin load down.
    • Compress text responses and export images at the size they are shown.
    • Use modern formats and HTTP/3 to cut transfer.
    • Remove unused load balancers, backends and forwarding rules.
    • Choose a Google Cloud region marked as low carbon for the origins, if data rules and latency allow it.
    • Google’s Carbon Footprint report is per project and service group, so quote no Cloud CDN-only figure.

    Pricing

    Purchase options

    Cache egress Per GiB, by region of the visitor

    Data served from the cache to visitors. Rates fall with volume and differ by destination region.

    Cache fill Per GiB, by origin and cache region

    Data moved from the origin into the cache when an object isn’t there yet. A better hit ratio means fewer fills.

    Cache lookups Per 10,000 requests

    Every request that reaches Cloud CDN counts, hit or miss.

    Load balancer Forwarding rules and data

    The external Application Load Balancer bills per forwarding rule hour and per GiB processed. Cache hits don’t pass through it.

    What you actually pay for

    • Cache egress to visitors, by destination region
    • Cache fill from the origin
    • Cache lookup requests, and invalidations beyond any free allowance
    • Forwarding rules and data processing on the load balancer
    • Cloud Armor policies, rules and requests, if you attach one

    Google lists cache egress, fill and lookup rates on its pricing page, and rates differ by region. See the official Cloud CDN pricing page and the Google Cloud Pricing Calculator.

    Important code references

    A static site: a Cloud Storage bucket, a backend bucket with Cloud CDN, cache mode, TTLs and a cache status header, and the load balancer in front of it, with a Google-managed certificate. The CLI tab builds it, adds a signing key and invalidates a path; Terraform describes the same resources. The Python tab signs a URL with a key and invalidates a path through the Compute API, and the C# tab audits backends for FORCE_CACHE_ALL, wide cache keys and CDN switched off. Replace the project, domain and names with your own.

    # Placeholders: replace the project and the domain with your own. The domain's DNS must point at the address created below.
    PROJECT=my-project-id
    BUCKET=$PROJECT-static-site
    DOMAIN=static.example.com
    
    # 1. A bucket for the site, readable by everyone, with one page. Cache-Control tells the edge and browsers how long to keep it.
    gcloud storage buckets create gs://$BUCKET --project $PROJECT --location asia-south1 --uniform-bucket-level-access
    gcloud storage buckets add-iam-policy-binding gs://$BUCKET --member allUsers --role roles/storage.objectViewer
    echo '<h1>Hello from the edge</h1>' > index.html
    gcloud storage cp index.html gs://$BUCKET/index.html --cache-control "public, max-age=300"
    
    # 2. A backend bucket with Cloud CDN switched on. CACHE_ALL_STATIC also caches plain static files that carry no cache headers.
    #    The custom header shows the cache status (hit or miss) on every response, which makes testing easy.
    gcloud compute backend-buckets create site-bucket --project $PROJECT --gcs-bucket-name $BUCKET --enable-cdn \
      --cache-mode CACHE_ALL_STATIC --default-ttl 3600 --client-ttl 600 --max-ttl 86400 --negative-caching \
      --custom-response-header "X-Cache-Status: {cdn_cache_status}"
    
    # 3. Put an external Application Load Balancer in front, with a global address, URL map, managed certificate, HTTPS proxy and forwarding rule.
    gcloud compute addresses create site-ip --project $PROJECT --global
    gcloud compute url-maps create site-map --project $PROJECT --default-backend-bucket site-bucket
    gcloud compute ssl-certificates create site-cert --project $PROJECT --domains $DOMAIN --global
    gcloud compute target-https-proxies create site-proxy --project $PROJECT --url-map site-map --ssl-certificates site-cert
    gcloud compute forwarding-rules create site-rule --project $PROJECT --global --address site-ip --target-https-proxy site-proxy \
      --ports 443 --load-balancing-scheme EXTERNAL_MANAGED
    
    # 4. Point DNS at this address, wait for the certificate to become ACTIVE, then ask for a page twice and read X-Cache-Status.
    IP=$(gcloud compute addresses describe site-ip --project $PROJECT --global --format="value(address)")
    echo "Create an A record: $DOMAIN -> $IP"
    gcloud compute ssl-certificates describe site-cert --project $PROJECT --global --format="value(managed.status)"
    curl -sI https://$DOMAIN/ | grep -i -E "^(HTTP|x-cache-status|age)"
    curl -sI https://$DOMAIN/ | grep -i -E "^(HTTP|x-cache-status|age)"
    
    # 5. After a release, invalidate the changed paths. Invalidation takes a few minutes to spread.
    gcloud compute url-maps invalidate-cdn-cache site-map --project $PROJECT --path "/index.html" --async
    
    # 6. For private files: add a signing key (keep the key file safe), then sign URLs with it.
    head -c 16 /dev/urandom | base64 | tr +/ -_ > key-1.txt
    gcloud compute backend-buckets add-signed-url-key site-bucket --project $PROJECT --key-name key-1 --key-file key-1.txt
    # Placeholders: pass in your own values. The ones below are examples.
    variable "project" {
      type = string
    }
    
    variable "domain" {
      type    = string
      default = "static.example.com"
    }
    
    provider "google" {
      project = var.project
    }
    
    resource "google_storage_bucket" "site" {
      name                        = "${var.project}-static-site"
      location                    = "ASIA-SOUTH1"
      uniform_bucket_level_access = true
    }
    
    # Public read. For private files use signed URLs instead and give the Cloud CDN service account read access.
    resource "google_storage_bucket_iam_member" "public" {
      bucket = google_storage_bucket.site.name
      role   = "roles/storage.objectViewer"
      member = "allUsers"
    }
    
    resource "google_compute_backend_bucket" "site" {
      name        = "site-bucket"
      bucket_name = google_storage_bucket.site.name
      enable_cdn  = true
    
      cdn_policy {
        cache_mode        = "CACHE_ALL_STATIC"
        default_ttl       = 3600
        client_ttl        = 600
        max_ttl           = 86400
        negative_caching  = true
        serve_while_stale = 86400
      }
    
      custom_response_headers = ["X-Cache-Status: {cdn_cache_status}"]
    }
    
    resource "google_compute_global_address" "site" {
      name = "site-ip"
    }
    
    resource "google_compute_url_map" "site" {
      name            = "site-map"
      default_service = google_compute_backend_bucket.site.id
    }
    
    resource "google_compute_managed_ssl_certificate" "site" {
      name = "site-cert"
    
      managed {
        domains = [var.domain]
      }
    }
    
    resource "google_compute_target_https_proxy" "site" {
      name             = "site-proxy"
      url_map          = google_compute_url_map.site.id
      ssl_certificates = [google_compute_managed_ssl_certificate.site.id]
    }
    
    resource "google_compute_global_forwarding_rule" "site" {
      name                  = "site-rule"
      target                = google_compute_target_https_proxy.site.id
      ip_address            = google_compute_global_address.site.address
      port_range            = "443"
      load_balancing_scheme = "EXTERNAL_MANAGED"
    }
    
    output "address" {
      value = google_compute_global_address.site.address
    }
    # pip install google-cloud-compute
    # Signs a URL for private content, and invalidates a path in the cache through the Compute API.
    import base64
    import datetime as dt
    import hashlib
    import hmac
    
    from google.cloud import compute_v1
    
    
    def sign_url(url, key_name, key_b64, expires):
        """Returns the URL with Expires, KeyName and Signature added. key_b64 is the URL-safe base64 key that was given to
        `gcloud compute backend-buckets add-signed-url-key`. The signature covers the whole URL, so don't change it afterwards."""
        expiry = int(expires.replace(tzinfo=dt.timezone.utc).timestamp()) if expires.tzinfo is None else int(expires.timestamp())
        separator = "&" if "?" in url else "?"
        to_sign = "%s%sExpires=%d&KeyName=%s" % (url, separator, expiry, key_name)
        digest = hmac.new(base64.urlsafe_b64decode(key_b64), to_sign.encode(), hashlib.sha1).digest()
        return "%s&Signature=%s" % (to_sign, base64.urlsafe_b64encode(digest).decode())
    
    
    def invalidate(project, url_map, path, host=None):
        """Asks every cache to drop the path. A single trailing * removes a whole prefix. It takes a few minutes to spread."""
        rule = compute_v1.CacheInvalidationRule(path=path, host=host) if host else compute_v1.CacheInvalidationRule(path=path)
        operation = compute_v1.UrlMapsClient().invalidate_cache(project=project, url_map=url_map, cache_invalidation_rule_resource=rule)
        return operation.name
    
    
    if __name__ == "__main__":
        key = open("key-1.txt").read().strip()
        expires = dt.datetime.now(dt.timezone.utc) + dt.timedelta(minutes=15)
        print(sign_url("https://static.example.com/private/report.pdf", "key-1", key, expires))
        print("invalidation operation:", invalidate("my-project-id", "site-map", "/index.html"))
    // dotnet add package Google.Cloud.Compute.V1
    // Audits the project's backends: FORCE_CACHE_ALL (private data can be cached), CDN switched off on a backend bucket,
    // and cache keys that include the whole query string, which splits the cache.
    using Google.Cloud.Compute.V1;
    
    string project = Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT") ?? throw new InvalidOperationException("Set GOOGLE_CLOUD_PROJECT first.");
    int problems = 0;
    
    BackendBucketsClient buckets = BackendBucketsClient.Create();
    foreach (BackendBucket bucket in buckets.List(project))
    {
        if (!bucket.EnableCdn)
        {
            Console.WriteLine($"backend bucket {bucket.Name}: Cloud CDN is switched off");
            problems++;
        }
        else if (bucket.CdnPolicy?.CacheMode == "FORCE_CACHE_ALL" && bucket.CdnPolicy.SignedUrlKeyNames.Count > 0)
        {
            Console.WriteLine($"backend bucket {bucket.Name}: FORCE_CACHE_ALL together with signed URLs, so check what is cached for whom");
            problems++;
        }
    }
    
    BackendServicesClient services = BackendServicesClient.Create();
    foreach (BackendService service in services.List(project))
    {
        if (!service.EnableCDN) continue;
    
        if (service.CdnPolicy?.CacheMode == "FORCE_CACHE_ALL")
        {
            Console.WriteLine($"backend service {service.Name}: FORCE_CACHE_ALL ignores private and no-store, so personal responses can be cached");
            problems++;
        }
        var key = service.CdnPolicy?.CacheKeyPolicy;
        if (key != null && key.IncludeQueryString && key.QueryStringWhitelist.Count == 0 && key.QueryStringBlacklist.Count == 0)
        {
            Console.WriteLine($"backend service {service.Name}: the whole query string is in the cache key, which splits the cache");
            problems++;
        }
    }
    
    Console.WriteLine(problems == 0 ? "No problems found." : $"{problems} problem(s) found.");
    return problems == 0 ? 0 : 1;

    Best videos to explore

    Videos picked for this service. Each one is labelled with its source, opens on YouTube if you prefer, and loads only when you press play.

    What is Cloud CDN?Official · Google Cloud · Beginner · Watch on YouTube
    Getting started with Cloud CDNOfficial · Google Cloud · Beginner · Watch on YouTube
    Google Cloud CDN in a minuteCommunity video · Beginner · Watch on YouTube
    Google Cloud CDN: Modern Architecture, Security, and Performance OptimizationCommunity video · Intermediate · Watch on YouTube

    Interview questions

    BasicWhat is Cloud CDN?

    It’s Google Cloud’s content delivery network. You turn it on for a backend of an external Application Load Balancer, and Google then caches responses in its edge locations, so visitors get repeat content from somewhere close and your servers see fewer requests.

    BasicWhat do you need before you can use Cloud CDN?

    An external Application Load Balancer, because Cloud CDN is a setting on its backend services or backend buckets. That means a forwarding rule, a URL map, a proxy and usually a certificate, and the load balancer’s charges come with it.

    BasicWhat are the three cache modes?

    USE_ORIGIN_HEADERS caches only responses that the origin marks as cacheable. CACHE_ALL_STATIC also caches ordinary static content that has no cache headers. FORCE_CACHE_ALL caches every successful response and ignores private and no-store, so it needs care.

    IntermediateHow does the cache key work, and how do you improve a low hit ratio?

    The key decides which requests count as the same object, and by default it includes the protocol, host, path and the full query string. If tracking parameters or the HTTP and HTTPS split create copies of the same file, exclude the protocol and the query string, or keep only the parameters that change the response, and the hit ratio rises.

    IntermediateHow do you release a new version without waiting for caches to expire?

    Use hashed file names so assets get new URLs, keep HTML TTLs short, and invalidate only the entry pages. Invalidation removes a path or a prefix with one trailing * and takes a few minutes, so it is a tool for exceptions and not the usual method.

    IntermediateHow would you serve private files through Cloud CDN?

    Keep the objects private and grant read access to the Cloud CDN service account, add a signing key to the backend, and have your application issue signed URLs or cookies with an expiry after it checks the user. Cloud CDN checks the signature and serves cached content to valid requests, so the origin sees little traffic.

    AdvancedWhen is FORCE_CACHE_ALL dangerous, and what is the alternative?

    It is dangerous whenever a response can differ per user, because the object is cached despite private or no-store and may reach someone else. Use it only for content that is identical for everyone, such as hashed static assets. For mixed backends use CACHE_ALL_STATIC or USE_ORIGIN_HEADERS and fix the headers at the origin.

    AdvancedHow would you put Cloud CDN in front of an origin outside Google Cloud?

    Create an internet network endpoint group that points at the origin’s host name, add it to a backend service with Cloud CDN enabled and a host header that the origin expects, and route to it from the URL map. Raise TTLs and use serve-while-stale so cache misses don’t flood the origin, and protect the origin so it accepts traffic only from Google.

    AdvancedWhat affects the cost of Cloud CDN, and how do you reduce it?

    Cache egress to visitors, cache fill from the origin and cache lookup requests are billed, together with the load balancer’s forwarding rule hours and data processing on traffic that isn’t served from the cache. A higher hit ratio cuts fills and load balancer data, compression cuts egress, and Cloud Armor rate limits stop abusive traffic. Check the invoice by SKU every month.

    AdvancedA deployment broke caching for a whole site. How do you find the cause?

    Compare the backend’s CDN settings and URL map with the last known good version in code. Look at the cache status header or the load balancer logs for hit and miss, check for a new Vary header, cookies or query strings in the cache key, and a change in cache mode or TTL. Roll back the setting, then fix the root cause and add an alert for the hit ratio.

    Similar or alternative services on other clouds

    CapabilityAWSAzureGoogle Cloud
    ServiceAmazon CloudFrontAzure Front DoorCloud CDN with an Application Load Balancer
    What it isA CDN with edge computeA CDN plus a global HTTP(S) load balancer and WAFA cache switched on for a load balancer backend
    OriginsS3, load balancers, API Gateway, VPC origins, any HTTP serverStorage, App Service, any public origin, Private Link origins (Premium)Cloud Storage buckets, backend services, external origins through an internet NEG
    Caching controlCache policies and behaviors per pathRoute caching settings and rule setsCache modes, TTLs and cache keys on the backend
    Code at the edgeCloudFront Functions and Lambda@EdgeRules engine for rewrites, redirects and headersService Extensions on the load balancer
    Web firewallAWS WAFFront Door WAFCloud Armor
    Private originOrigin access control, VPC originsPrivate Link origins (Premium)Backends inside the VPC behind the load balancer
    CertificatesFree ACM certificates, in us-east-1Managed certificates for custom domainsGoogle-managed certificates on the load balancer
    How you are billedData out and requests, or a flat-rate planBase fee per profile, plus data and requestsCache egress, cache fill and lookups, plus the load balancer

    Typical origins are Cloud Storage and Cloud Run, in front of a load balancer from Cloud Load Balancing. Signing keys belong in Secret Manager, and metrics and logs go to Cloud Monitoring.

    Did you find this article helpful?

    Your answer helps us improve this page for the next reader.

    Sources and further reading

    CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.