Home / Networking

How to Build an HA External HTTPS Load Balancer on GCP — Multi-Region Backends, Cloud CDN, Managed Certs | 2026

How to Build an HA External HTTPS Load Balancer on GCP — Multi-Region Backends, Cloud CDN, Managed Certs | 2026

A Google Cloud external HTTPS load balancer is a global Layer 7 proxy that terminates TLS, distributes traffic across multi-region backends, and caches content at the edge with Cloud CDN. This guide shows you how to deploy a production-ready HA setup strictly using Terraform HCL.

By Mateusz Chmielewski · Jul 27, 2026 · 14 min read

What Is a GCP External HTTPS Load Balancer?

The Global External HTTP(S) Load Balancer is a fully managed, global Layer 7 (HTTP/HTTPS) load balancer built on Google Front Ends (GFEs). It terminates client TLS, applies routing rules, optionally caches responses via Cloud CDN, and forwards traffic to backend services such as managed instance groups, Cloud Run, or GKE.

Think of it as a smart traffic director at a global airport: passengers (users) arrive at the closest terminal (edge POP), security checks their ticket (SSL termination), and they are routed to the correct gate (backend) in the right region based on capacity and rules.

ConceptExplanationWhen to use
URL MapLayer 7 routing rules that map hostnames and paths to backend services.Multi-service routing, API versioning, microservices
Backend ServiceLogical grouping of backends with health checks, session affinity, and CDN policies.High availability across regions and instance groups
Managed SSL CertificateGoogle-provisioned and auto-renewed TLS certificate for your custom domain.Production HTTPS endpoints with custom domains
Cloud CDNGlobal content delivery network that caches responses at Google edge PoPs.Static assets, API read-heavy workloads, latency reduction
Health CheckProbes that determine backend availability and trigger failover.Any production backend requiring automatic failover

Why Use a Global External HTTPS Load Balancer?

Serving global traffic from a single region creates high latency for distant users, a single point of failure, and certificate management overhead. Self-managed load balancers also require capacity planning and patching.

GCP's global external HTTPS load balancer provides anycast IP routing, automatic multi-region failover, managed TLS certificates, and Cloud CDN caching — all fully automated with HashiCorp Terraform. Pair with [Static Egress Gateways](/tutorial/cloud-run-gke-static-egress-ip-terraform-serverless-vpc-access-nat), [VPC Service Controls](/tutorial/terraform-vpc-service-controls-custom-module-guide), and [GKE Spot VMs](/tutorial/spot-vms-preemptible-gke-cost-optimization).

FeaturethisServicealtAaltB
Global Anycast IPYes — single global VIPNo — regional onlyManual multi-region DNS
Managed SSL CertificatesFree, auto-renewedSelf-managed or paidSelf-managed
Cloud CDN IntegrationNative one-flag enableSeparate serviceThird-party integration
Health-Based FailoverAutomaticManual or scriptedDNS failover only

Prerequisites

  • GCP Organization Account with active billing
  • Terraform v1.5+ installed and authenticated
  • A registered public DNS domain with Cloud DNS zone configured
  • IAM roles: Compute Network Admin, Compute Security Admin, Compute Instance Admin, DNS Administrator

Step-by-Step Guide

Step 1: Configure GCP Provider and Enable APIs

Define the Google Terraform provider and enable required GCP service APIs asynchronously in Terraform. Managing API activation in Terraform ensures zero manual GCP Console clicks during provisioning.

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.project_id
  region  = "europe-west1"
}

resource "google_project_service" "compute_api" {
  service            = "compute.googleapis.com"
  disable_on_destroy = false
}

Step 2: Reserve Global Static IPv4 Address

Declare a global external IP address resource in Terraform for the HTTPS load balancer frontend. A static IP ensures your DNS records remain permanent regardless of load balancer re-deployments.

resource "google_compute_global_address" "lb_ip" {
  name         = "web-lb-global-ip"
  ip_version   = "IPV4"
  address_type = "EXTERNAL"
}

output "load_balancer_ip" {
  value       = google_compute_global_address.lb_ip.address
  description = "The public global IPv4 address of the load balancer"
}

Step 3: Provision Multi-Region Managed Instance Groups

Create instance templates and regional managed instance groups across US and EU regions. Multi-region instance groups allow the load balancer to route traffic away from a failed region automatically.

resource "google_compute_instance_template" "web_template" {
  name_prefix  = "web-template-"
  machine_type = "e2-medium"
  tags         = ["allow-health-check"]

  disk {
    source_image = "debian-cloud/debian-12"
    auto_delete  = true
    boot         = true
  }

  network_interface {
    network = "default"
    access_config {}
  }

  metadata_startup_script = <<-EOF
    #!/bin/bash
    apt-get update && apt-get install -y nginx
    echo "<h1>Hello from $(hostname)</h1>" > /var/www/html/index.html
    systemctl start nginx
  EOF

  lifecycle {
    create_before_destroy = true
  }
}

resource "google_compute_region_instance_group_manager" "mig_us" {
  name               = "web-mig-us-central1"
  region             = "us-central1"
  base_instance_name = "web-us"
  target_size        = 2

  version {
    instance_template = google_compute_instance_template.web_template.id
  }
}

resource "google_compute_region_instance_group_manager" "mig_eu" {
  name               = "web-mig-europe-west1"
  region             = "europe-west1"
  base_instance_name = "web-eu"
  target_size        = 2

  version {
    instance_template = google_compute_instance_template.web_template.id
  }
}

Step 4: Configure Health Check Firewall Rules

Create a Terraform firewall resource permitting ingress from Google's health check probe IP ranges. Without this firewall rule, health probes fail and backends are marked unhealthy, causing HTTP 502 errors.

resource "google_compute_firewall" "allow_health_checks" {
  name    = "allow-lb-and-healthchecks"
  network = "default"

  allow {
    protocol = "tcp"
    ports    = ["80", "443"]
  }

  # Fixed Google Health Check IP probe ranges
  source_ranges = [
    "130.211.0.0/22",
    "35.191.0.0/16"
  ]

  target_tags = ["allow-health-check"]
}

Step 5: Define Global HTTP Health Check

Declare a global HTTP health check resource that probes backends for automatic failover. Health checks are the foundation of load balancer high availability and 99.99% SLA.

resource "google_compute_health_check" "web_health_check" {
  name                = "web-health-check"
  check_interval_sec  = 10
  timeout_sec         = 5
  healthy_threshold   = 2
  unhealthy_threshold = 3

  http_health_check {
    port         = 80
    request_path = "/"
  }
}

Step 6: Create Backend Service with Cloud CDN

Group multi-region instance groups into a global backend service and enable Cloud CDN caching in Terraform. The backend service manages load distribution, and Cloud CDN caches static content at Google edge PoPs.

resource "google_compute_backend_service" "web_backend" {
  name                  = "web-backend-service"
  protocol              = "HTTP"
  port_name             = "http"
  load_balancing_scheme = "EXTERNAL_MANAGED"
  health_checks         = [google_compute_health_check.web_health_check.id]

  enable_cdn = true

  cdn_policy {
    cache_mode                   = "CACHE_ALL_STATIC"
    default_ttl                  = 3600
    max_ttl                      = 86400
    client_ttl                   = 7200
    negative_caching             = true
    signed_url_cache_max_age_sec = 7200
  }

  backend {
    group            = google_compute_region_instance_group_manager.mig_us.instance_group
    balancing_mode   = "UTILIZATION"
    capacity_scaler  = 1.0
    max_utilization = 0.8
  }

  backend {
    group            = google_compute_region_instance_group_manager.mig_eu.instance_group
    balancing_mode   = "UTILIZATION"
    capacity_scaler  = 1.0
    max_utilization = 0.8
  }
}

Step 7: Declare URL Map and Google-Managed SSL Certificate

Define Layer 7 URL map routing rules and request an auto-renewed Google-managed TLS certificate. Google-managed certificates eliminate manual TLS renewal overhead and certificate expiry outages.

resource "google_compute_managed_ssl_certificate" "web_cert" {
  name = "web-managed-ssl-cert"

  managed {
    domains = [var.domain_name]
  }
}

resource "google_compute_url_map" "web_url_map" {
  name            = "web-url-map"
  default_service = google_compute_backend_service.web_backend.id
}

Step 8: Target HTTPS Proxy and Global Forwarding Rule

Bind the URL map, SSL certificate, and static global IP address into an HTTPS forwarding rule. This creates the public entry point on port 443 that terminates TLS and proxies traffic to backends.

resource "google_compute_target_https_proxy" "web_proxy" {
  name             = "web-target-https-proxy"
  url_map          = google_compute_url_map.web_url_map.id
  ssl_certificates = [google_compute_managed_ssl_certificate.web_cert.id]
}

resource "google_compute_global_forwarding_rule" "https_forwarding_rule" {
  name                  = "web-https-forwarding-rule"
  target                = google_compute_target_https_proxy.web_proxy.id
  port_range            = "443"
  ip_address            = google_compute_global_address.lb_ip.id
  load_balancing_scheme = "EXTERNAL_MANAGED"
  network_tier          = "PREMIUM"
}

Step 9: Configure DNS A Record in Cloud DNS

Point your custom domain DNS A record to the reserved load balancer global static IP address in Terraform. Users access your app via domain, and Google DNS validation completes managed SSL issuance.

resource "google_dns_record_set" "web_dns" {
  name         = "${var.domain_name}."
  type         = "A"
  ttl          = 300
  managed_zone = var.dns_zone_name
  rrdatas      = [google_compute_global_address.lb_ip.address]
}

Step 10: Apply Terraform Plan and Verify Deployment

Execute terraform apply and verify HTTPS status, Cloud CDN cache headers, and failover health. Automated verification confirms end-to-end TLS termination and edge caching performance.

# Apply Terraform Plan
# terraform init && terraform apply -auto-approve

# Verification Commands
# curl -I https://www.example.com/
# curl -I https://www.example.com/static/image.png

Verification & Health Check

Best Practices

  • Use Regional Managed Instance Groups, Not Zonal
  • Enable Cloud CDN with Appropriate Cache Modes
  • Pin Load Balancer to Premium Network Tier

Common Mistakes

  • {"errorCode":"HTTP 502 / backend_unhealthy","symptoms":"Browser shows 502 Bad Gateway; Cloud Logging shows backends failing health checks.","rootCause":"Firewall rules block Google health check probes or the application does not respond on the health check path/port.","fixCommand":"resource \"google_compute_firewall\" \"allow_health_checks\" {\n source_ranges = [\"130.211.0.0/22\", \"35.191.0.0/16\"]\n}\n","prevention":"Always allow the fixed health check IP ranges and test the health endpoint locally before attaching it to the LB."}
  • {"errorCode":"SSL_CERTIFICATE_PROVISIONING_FAILED","symptoms":"Managed certificate status remains FAILED or PROVISIONING for hours.","rootCause":"DNS A record does not point to the load balancer IP, or the domain's CAA records block Let's Encrypt / Google Trust Services.","fixCommand":"resource \"google_dns_record_set\" \"web_dns\" {\n rrdatas = [google_compute_global_address.lb_ip.address]\n}\n","prevention":"Create the A record in Terraform before provisioning the certificate and ensure CAA records include `issue: pki.goog`."}
  • {"errorCode":"CACHE_MISS for every static request","symptoms":"Cloud CDN always fetches from origin; cache hit ratio near zero.","rootCause":"Response headers contain `Cache-Control: private, no-store` or the request includes cookies that bust the cache key.","fixCommand":"# In your application or Nginx config:\n# add_header Cache-Control \"public, max-age=3600\";\n","prevention":"Configure web servers to emit cache-friendly headers for static content and use signed URLs or cookies for personalized dynamic content."}

Cost Analysis

Featuremetriccost1kcost10kcost100kcost1m
Forwarding Rule (first 5)$0.00$0.00$0.03$0.30
Processed Data (GB)$0.00$0.10$1.00$10.00
Cloud CDN Egress$0.00$0.08$0.80$8.00
Backend Compute (2x e2-medium per region × 2 regions)$30.00$30.00$30.00$30.00
Managed SSL Certificate$0.00$0.00$0.00$0.00

References

Browse all tutorials