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.
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:
- Global versus regional. Azure Front Door is global and lives at the edge. Application Gateway is regional and lives in your virtual network. They are not alternatives; plenty of estates run both.
- CDN versus edge platform. Caching is one feature. Routing, TLS termination, WAF, DDoS absorption, and rules processing are the rest, and they matter more.
- Layer 7 versus layer 4. These services front HTTP and HTTPS. For raw TCP or UDP you need something else: Azure Load Balancer, AWS Global Accelerator, or a GCP network load balancer.
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.
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.
- CloudFront is the CDN and edge: caching, TLS termination, edge compute through CloudFront Functions and Lambda@Edge.
- AWS WAF attaches to the CloudFront distribution and gives you managed rule groups, rate limiting, and Bot Control.
- AWS Shield is the DDoS layer. Standard is on by default; Advanced adds response team support and cost protection.
- Route 53 handles DNS and global routing policies.
- Global Accelerator gives you anycast entry for traffic that is not HTTP, or where you want static IPs.
- Origin Access Control and Origin Shield protect and consolidate access to the origin.
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.
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.
- Cloud CDN is effectively a switch on the backend service.
- Cloud Armor is the WAF and DDoS layer: preconfigured rules, rate limiting, geo restrictions, bot management, and adaptive protection.
- Identity-Aware Proxy puts identity in front of the application at the edge, which is the piece the other two do not have in quite the same way.
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
| Capability | Azure | AWS | GCP |
|---|---|---|---|
| global edge | Front Door (Standard, Premium) | CloudFront | Global External Application LB |
| waf | Front Door WAF (Premium for managed rules) | AWS WAF (attached to the distribution) | Cloud Armor (on the backend service) |
| ddos | Azure DDoS Protection, absorbed at the edge | Shield Standard, Shield Advanced | Cloud Armor, built in at the front end |
| cdn | Built into Front Door | CloudFront is the CDN | Cloud CDN, a flag on the backend |
| private origin | Private Link origins (Premium) | Origin Access Control, prefix list, VPC origins | Front end ranges plus firewall rules |
| regional waf | Application Gateway WAF v2 | AWS WAF on an ALB | Regional external ALB with Cloud Armor |
| non-http | Azure Load Balancer | Global Accelerator, NLB | Network load balancer |
| hybrid origin | Any HTTP endpoint, ExpressRoute | Custom origin, Direct Connect | Hybrid NEG, Interconnect |
| edge compute | Rules engine | CloudFront Functions, Lambda@Edge | Limited, use Cloud Run |
| identity at edge | Entra ID upstream | Lambda@Edge or Cognito | Identity-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
- Origin lockdown. The single most common failure. A WAF at the edge is decorative if your origin still answers requests from the internet. Use Private Link on Azure, Origin Access Control or the CloudFront prefix list on AWS, and front end ranges plus firewall rules on GCP. Then test it: curl the origin directly and confirm you are refused.
- Prevention mode. WAFs go into detection mode "just for a week" during rollout and quietly stay there for a year. Detection logs an attack. Prevention stops it. Put a date on the switch.
- Rate limiting. Cheap, effective, and skipped. It blunts credential stuffing and scraping before either reaches your application.
- Bot management. A large share of your traffic is automated. Some of it is welcome, most of it is not.
- Geo filtering. If you only serve the UK, saying so at the edge removes a lot of noise.
- TLS floor. Set a minimum version. The default is often more permissive than your compliance team assumes.
- Header verification. Belt and braces on origin lockdown: have the edge inject a secret header and have the origin reject anything without it.
- Logs into the SIEM. WAF logs are an attack feed. Send them to Sentinel, to CloudWatch, or to Cloud Logging, and alert on the blocks.
The gotchas
- Picking the wrong Azure tier. Standard has no managed WAF rule sets and no Private Link origins. Teams discover this after go-live.
- Confusing global with regional. Front Door is not Application Gateway, and CloudFront is not an ALB. They solve different problems and often coexist.
- The us-east-1 rule. CloudFront ACM certificates and CloudFront-scoped WAF ACLs must live in us-east-1, whatever region you actually run in.
- Caching what should never be cached. A cache key that ignores the auth header can serve one user's response to another. This is a real breach class, not a theoretical one.
- Health probes that lie. A probe hitting a static path returns healthy while the application is broken behind it. Probe something that exercises the app.
- Forgetting the layer 4 case. None of these front raw TCP or UDP. That is a different service.
- Cost surprises. Edge pricing is usage-based and, on Azure Premium, carries a meaningful base fee. Model it before you commit.
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?