Cloud Security

The global edge: Azure Front Door, the AWS equivalent, and the GCP one, compared

Saleem Yousaf 16 July 2026 ~18 min read

TLS terminates there. The web application firewall runs there. DDoS is absorbed there. Every request your users make arrives there first. And yet the global edge gets a fraction of the attention we give to ingress controllers and service meshes.

For most internet-facing applications, the edge is the real perimeter. It is the first thing an attacker meets and the last thing that stands between a botnet and your origin. It deserves to be an architectural decision, not a checkbox someone ticked during a migration.

The thesis: the global edge is the most underrated security boundary in cloud architecture. Teams argue for weeks about mesh sidecars, then put a CDN in front of production, leave the WAF in detection mode, and forget to lock the origin. The door is impressive. The back door is wide open.

What we are actually talking about

The global edge is an anycast layer in front of your application. One hostname, one address, hundreds of points of presence. A user's request enters the provider's network at the nearest edge, gets inspected and possibly cached, then travels the provider's private backbone to your origin. You get latency and availability benefits, and, more importantly here, you get a place to enforce security before traffic reaches anything you own.

Three things get muddled constantly, so let us separate them:

Azure Front Door

Front Door is Microsoft's global entry point: anycast routing, TLS termination, caching, WAF, and DDoS protection in one profile, running on the same backbone that carries Microsoft 365, across roughly 190 or more points of presence.

Two tiers matter. Standard gives you global layer 7 load balancing and CDN. Premium adds the managed WAF rule sets, bot protection, and, the one that changes your architecture, Private Link origins, so Front Door reaches your backend privately and your origin never needs a public endpoint. Front Door Classic is the legacy generation and is closed to new deployments, so do not start there.

azure Users global Front Door anycast edge TLS + cache WAF + DDoS rules engine private link Azure origin App Service, AKS expressroute On-premises hybrid origin cloud hybrid origin lockdown Private Link, or the AzureFrontDoor.Backend service tag plus the X-Azure-FDID header. Public origin access blocked.
Azure Front Door. Cloud origins over Private Link, hybrid origins over ExpressRoute, and the rule that matters most: nobody reaches the origin except through the front door. Click to enlarge.

Cloud model. Front Door in front of App Service, AKS, Static Web Apps, or Azure Storage. With Premium, Private Link origins mean the backend has no public endpoint at all. This is the pattern to aim for.

Hybrid model. Front Door will front any reachable HTTP endpoint, including a data centre, so it is a genuinely useful way to put a modern edge in front of a legacy on-premises application. Pair it with ExpressRoute for the private path, and treat the origin lockdown as mandatory rather than optional.

Terraform

The current provider uses the cdn_frontdoor resources. A minimal Premium profile with a WAF policy:

resource "azurerm_cdn_frontdoor_profile" "fd" {
  name                = "fd-prod"
  resource_group_name = azurerm_resource_group.rg.name
  sku_name            = "Premium_AzureFrontDoor"   # Premium for managed WAF + Private Link
}

resource "azurerm_cdn_frontdoor_firewall_policy" "waf" {
  name                = "wafprod"
  resource_group_name = azurerm_resource_group.rg.name
  sku_name            = azurerm_cdn_frontdoor_profile.fd.sku_name
  enabled             = true
  mode                = "Prevention"              # not Detection. see the gotchas

  managed_rule {
    type    = "Microsoft_DefaultRuleSet"
    version = "2.1"
    action  = "Block"
  }

  custom_rule {
    name     = "ratelimit"
    type     = "RateLimitRule"
    action   = "Block"
    priority = 100
    rate_limit_threshold = 1000
    rate_limit_duration_in_minutes = 1
    match_condition {
      match_variable = "RemoteAddr"
      operator       = "IPMatch"
      match_values   = ["0.0.0.0/0"]
    }
  }
}

You then add an endpoint, an origin group with health probes, an origin, a route, and a security policy that binds the WAF to the domain. The shape is verbose but predictable.

Portal

Create a Front Door and CDN profile, choose Premium, add an endpoint, define an origin group with a health probe, add your origin (enable Private Link here), add a route mapping the domain and path to the origin group, then create a WAF policy and associate it with the domain. Then, and people forget this, go and close the origin's public access.

AWS: there is no single equivalent, and that is the point

Ask for "the AWS Front Door" and you get a shrug, because AWS splits the same job across several services. That is not a flaw, it is a different philosophy: purpose-built components you compose.

So Azure Front Door is roughly CloudFront plus AWS WAF plus Shield, with a bit of Route 53 and Global Accelerator depending on what you are doing.

aws Users global Route 53 DNS CloudFront edge + cache AWS WAF Shield DDoS Origin Shield OAC AWS origin S3, ALB, API GW direct connect Custom origin on-premises cloud hybrid origin lockdown Origin Access Control for S3. For an ALB, restrict to the CloudFront prefix list and verify a shared secret header.
The AWS edge, assembled from parts. Same job as Front Door, more pieces, more control. Click to enlarge.

Cloud model. CloudFront in front of S3 with Origin Access Control, or in front of an Application Load Balancer or API Gateway, with AWS WAF attached to the distribution.

Hybrid model. CloudFront supports custom origins, so an on-premises web server works, typically reached over Direct Connect or a VPN. Global Accelerator is the option when the traffic is not HTTP, or you need fixed anycast IPs in front of on-premises endpoints.

Terraform

resource "aws_wafv2_web_acl" "edge" {
  name  = "edge-acl"
  scope = "CLOUDFRONT"          # must be us-east-1 for CloudFront
  default_action { allow {} }

  rule {
    name     = "common"
    priority = 1
    override_action { none {} }
    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesCommonRuleSet"
        vendor_name = "AWS"
      }
    }
    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "common"
      sampled_requests_enabled   = true
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "edge-acl"
    sampled_requests_enabled   = true
  }
}

resource "aws_cloudfront_origin_access_control" "oac" {
  name                              = "s3-oac"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "cdn" {
  enabled     = true
  web_acl_id  = aws_wafv2_web_acl.edge.arn

  origin {
    domain_name              = aws_s3_bucket.site.bucket_regional_domain_name
    origin_id                = "s3origin"
    origin_access_control_id = aws_cloudfront_origin_access_control.oac.id
  }

  default_cache_behavior {
    target_origin_id       = "s3origin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
    cache_policy_id        = data.aws_cloudfront_cache_policy.optimized.id
  }

  viewer_certificate {
    acm_certificate_arn      = aws_acm_certificate.cert.arn
    minimum_protocol_version = "TLSv1.2_2021"
    ssl_support_method       = "sni-only"
  }

  restrictions { geo_restriction { restriction_type = "none" } }
}

Note the trap in that first block: a CloudFront web ACL must be created in us-east-1, whatever region the rest of your stack lives in.

Console

Create the distribution, set the origin (choose Origin Access Control for S3, and let the console update the bucket policy for you), attach a WAF web ACL, set the viewer protocol policy to redirect to HTTPS, set a minimum TLS version, and attach the ACM certificate from us-east-1.

GCP: one product, fewer moving parts

Google's answer is the Global External Application Load Balancer, and it is the tidiest of the three. One anycast IP, and Cloud CDN and Cloud Armor are configuration on the backend service rather than separate products to wire together. Traffic enters Google's network at the nearest point of presence and rides the private backbone from there.

gcp Users global one anycast IP Global ALB Google front end Cloud Armor WAF Cloud CDN IAP identity backend service GCP backend GKE, Cloud Run, MIG hybrid NEG On-premises via Interconnect cloud hybrid origin lockdown Backends take traffic only from the Google front end ranges. Cloud Armor policy attaches to the backend service.
GCP keeps it in one place. CDN and WAF are settings on the backend service, not separate products to assemble. Click to enlarge.

Cloud model. The global load balancer in front of GKE, Cloud Run, or managed instance groups, with Cloud Armor attached to the backend service and Cloud CDN enabled where caching helps.

Hybrid model. This is GCP's neat trick: a hybrid network endpoint group lets the global load balancer treat an on-premises or even another cloud's endpoint as a backend, reached over Cloud Interconnect. It is the cleanest hybrid story of the three.

Terraform

resource "google_compute_security_policy" "armor" {
  name = "edge-armor"

  rule {
    action   = "throttle"
    priority = 100
    match {
      versioned_expr = "SRC_IPS_V1"
      config { src_ip_ranges = ["*"] }
    }
    rate_limit_options {
      conform_action = "allow"
      exceed_action  = "deny(429)"
      enforce_on_key = "IP"
      rate_limit_threshold {
        count        = 1000
        interval_sec = 60
      }
    }
  }

  rule {
    action   = "deny(403)"
    priority = 200
    match {
      expr { expression = "evaluatePreconfiguredExpr('xss-v33-stable')" }
    }
  }

  rule {
    action   = "allow"
    priority = 2147483647
    match {
      versioned_expr = "SRC_IPS_V1"
      config { src_ip_ranges = ["*"] }
    }
  }
}

resource "google_compute_backend_service" "be" {
  name            = "web-backend"
  protocol        = "HTTPS"
  enable_cdn      = true                # Cloud CDN is a flag, not a product
  security_policy = google_compute_security_policy.armor.id
  health_checks   = [google_compute_health_check.hc.id]

  backend {
    group = google_compute_region_network_endpoint_group.neg.id
  }
}

Console

Create a global external application load balancer, define the backend service, tick Cloud CDN, attach a Cloud Armor policy, add the URL map and host rules, then attach a Google-managed certificate to the HTTPS target proxy.

Side by side

CapabilityAzureAWSGCP
global edgeFront Door (Standard, Premium)CloudFrontGlobal External Application LB
wafFront Door WAF (Premium for managed rules)AWS WAF (attached to the distribution)Cloud Armor (on the backend service)
ddosAzure DDoS Protection, absorbed at the edgeShield Standard, Shield AdvancedCloud Armor, built in at the front end
cdnBuilt into Front DoorCloudFront is the CDNCloud CDN, a flag on the backend
private originPrivate Link origins (Premium)Origin Access Control, prefix list, VPC originsFront end ranges plus firewall rules
regional wafApplication Gateway WAF v2AWS WAF on an ALBRegional external ALB with Cloud Armor
non-httpAzure Load BalancerGlobal Accelerator, NLBNetwork load balancer
hybrid originAny HTTP endpoint, ExpressRouteCustom origin, Direct ConnectHybrid NEG, Interconnect
edge computeRules engineCloudFront Functions, Lambda@EdgeLimited, use Cloud Run
identity at edgeEntra ID upstreamLambda@Edge or CognitoIdentity-Aware Proxy

The honest summary: Azure consolidates the most into one product, which makes it the easiest to reason about and the easiest to get wrong if you pick Standard and then need Premium features. AWS gives you the most control and the most parts to assemble, so it rewards teams who like composing primitives. GCP has the cleanest model, one load balancer with security and caching as settings, and the best hybrid backend story.

The security features people underuse

The gotchas

So why is it underrated?

My honest theory: the edge is boring in the way that load-bearing walls are boring. It is provisioned once, usually during a migration, often by whoever was closest to the DNS. It does not get a conference track. Nobody gets promoted for tuning a WAF rule set. And because it works, quietly, from day one, nobody revisits it.

But it is where your TLS terminates, where your DDoS is absorbed, and where the first hostile request of the day arrives. If a service mesh deserves a design review, so does the thing standing between the entire internet and your application.

Two questions worth asking about your own estate this week. Can anyone reach your origin without going through the edge? And is your WAF actually blocking, or just taking notes?