You can now route your users to the nearest Google datacenter to them that has your Cloud Run application deployed. In this article, I list the commands to setup a load balancer and deploy an application as “multi-region” with Cloud Run using gcloud.

You can do this on Cloud Console web site as well, but in this blog post, I am providing the CLI version of the story, and share a bash script, as well as a working demo.

Step 0: Identify the Cloud Run regions you want to deploy

regions=(us-central1 asia-east1 europe-west4 australia-southeast1)
Learn how to get Cloud Run regions from the REST API in bash
project="$(gcloud config get-value core/project -q)
access_token="$(gcloud auth print-access-token)"
curl -sSLfH "Authorization: Bearer $access_token" \
        "$project/locations?alt=json" |\
        jq -r '.locations[].locationId'

Step 1: Deploy the app to multiple regions

I wrote an application that prints the flag of country the datacenter is running at. You can use this to try things out.

for region in $regions; do
    gcloud run deploy zoneprinter
        --platform=managed --allow-unauthenticated \

Step 2: Understand a load balancer is many components put together.

Take a look at the diagram in is article. You’ll learn that, under the covers, a “Cloud HTTP(S) Balancer” is not a single API object, but rather quite a few API objects associated to each other.

Step 3: Create regional serverless network endpoint groups (NEGs)

for region in $regions; do
    gcloud alpha compute network-endpoint-groups create \
        --region=$region --network-endpoint-type=SERVERLESS \
        --cloud-run-service=zoneprinter \

Step 3: Create global backend service

gcloud compute backend-services create --global \

Step 3: Add regional NEGs to the backend

for region in $regions; do
    gcloud alpha compute backend-services add-backend zoneprinter-backend \
        --network-endpoint-group-region=$region \

Step 4: Create URL Map for the backend

gcloud compute url-maps create zoneprinter-urlmap \

Step 5: Create a managed SSL certificate

Did you know Google can automatically provision TLS certificates for your domains for free? Decide on a domain name for your app.

gcloud beta compute ssl-certificates create zoneprinter-cert \

Step 6: Create a Target HTTP(S) Proxy

gcloud compute target-https-proxies create zoneprinter-https \
    --ssl-certificates=zoneprinter-cert \

Step 7: Create global forwarding rule

gcloud compute forwarding-rules create --global zoneprinter-lb \
    --target-https-proxy=zoneprinter-https \

Step 8: Find the IP address of the load balancer

gcloud compute forwarding-rules describe --global zoneprinter-lb \

This is an ephemeral IP (i.e. if you delete and recreate the forwarding rule, you’ll get a different IP, however you can create a global static IP and associate it in the previous step with --address option.)

Step 9: Configure your domain’s DNS records

Take this IP address and update your domain’s (e.g. above) DNS records with this IP address.

Step 10: Now, patiently wait…

Now, (1) Google is reconfiguring its global network, (2) solving a TLS challenge to get you a managed certificate (3) and your DNS provider is updating your DNS records. All this can take up to 30 minutes. Wait patiently until this command shows status: ACTIVE:

gcloud beta compute ssl-certificates describe zoneprinter-cert

If all goes well, you’ll get a globally load-balanced endpoint with Cloud Run. If you’re lazy, check out a demo I deployed. 😉


I wrote a bash script that does these steps for you. (You can configure it via $PROJECT_ID, $IMAGE, $APP_NAME, $DOMAIN environment variables.)

This integration of Cloud Run and Cloud HTTP(S) Load Balancer is now possible with serverless NEGs, which is currently in beta. You can also read this guide to learn more.

This feature enables a ton of new products to be used with Cloud Run, such as Cloud CDN, Cloud Armor (DDoS/WAF) and soon Cloud IAP. Similarly, you can use this to have static IP addresses for your Cloud Run applications.

P.S. If you want to prevent long-term charges to your account, you should clean up the resources by using the delete equivalent of each create command and by following the steps backwards.