CloudFront to a load balancer: VPC origins or a locked-down public ALB

Two ways to put CloudFront in front of an ALB — a VPC origin that reaches an internal ALB in private subnets (dual-stack since October 2026), or a public ALB whose security group admits only CloudFront's origin-facing prefix list — with what each side needs, a known-good setup for each, and the 502/504/403 that the known-bad ones produce.

markdownpatternv463BT-KWT6stage: buildtrust: officialservice: cloudfrontservice: elbinterface: iacinterface: cliCloudFront VPC originsCreateVpcOriginCloudFront-VPCOrigins-Service-SGcom.amazonaws.global.cloudfront.origin-facingCloudFront ALB origininternal ALB CloudFrontdual-stack VPC originorigin certificate mismatchCloudFront 504 ALBCloudFront 502 ALB

Created 18 Oct 2026 · Modified 23 Oct 2026 · 4 versions

CloudFront to a load balancer

Prefer a VPC origin. The ALB becomes internal, in private subnets, and CloudFront is the only way in. Use a public ALB only where VPC origins aren't supported. In that case, restrict its security group to CloudFront's origin-facing prefix list.

Option 1: VPC origin (private ALB)

What crosses the handoff

SideProvides / expects
CloudFrontA VPC origin resource (CreateVpcOrigin) naming the ALB's ARN. CloudFront creates a service-managed network interface in your private subnet and a security group named CloudFront-VPCOrigins-Service-SG. Don't edit that group, and don't name your own groups that way. The VPC origin takes up to 15 minutes to reach Deployed.
VPC / ALBAn internal ALB that is Active, in a VPC with an internet gateway attached (it marks the VPC as internet-receiving; you don't route to it). A private subnet with a free IPv4 address (and IPv6 for dual-stack). The ALB's security group admits the listener port from CloudFront-VPCOrigins-Service-SG (tighter) or from the prefix list com.amazonaws.global.cloudfront.origin-facing (plus com.amazonaws.global.ipv6.cloudfront.origin-facing for dual-stack). The outbound NACL allows ephemeral ports 1024–65535. Inbound NACL rules aren't evaluated for this traffic.

Known-good

  1. Internal ALB in two private subnets, with a security group admitting 443 from the service-managed group.
  2. VPC origin created (IPv4, or dual-stack since 2026-10-15) and Deployed.
  3. Distribution origin is the VPC origin. Use HTTPS to the ALB with a certificate whose name matches the origin domain (see below).
  4. Viewer certificate in ACM us-east-1; ALB certificate in the ALB's Region.
  5. Existing public setups migrate through a staging distribution: test the VPC origin, promote, then make the subnets private.

WebSockets through VPC origins are supported (2026-05-01; no extra cost). Not supported: gRPC, Lambda@Edge origin request/response triggers, Gateway Load Balancers, NLBs with TLS listeners (NLBs also need a security group). VPC origins exist in most commercial Regions, with some AZ exceptions. Check the list on the VPC origins page before you design.

Option 2: public ALB, locked down

SideProvides / expects
CloudFrontA custom origin whose domain is the ALB's DNS name or, better, a name of yours that is on the ALB's certificate.
ALBInternet-facing, in public subnets. Its security group admits 443 only from the prefix list com.amazonaws.global.cloudfront.origin-facing. That prefix list counts against the rules-per-group quota by its weight, which can be large (reference/vpc/security-groups-and-nacls.md).

The prefix list stops direct access from outside CloudFront's ranges. It doesn't stop other CloudFront distributions from using your ALB as an origin. For that, add a check at the ALB, such as a secret header or WAF rule (UNVERIFIED: a common practice, not in the collected sources), or use Option 1.

Origin TLS, for both options

CloudFront verifies the origin certificate. One of its names must match the origin domain name (or the Host header CloudFront forwards), and the chain must be complete and from a CA on Mozilla's list. Otherwise you get 502 with X-Cache: Error from cloudfront. The ALB's default …elb.amazonaws.com name can't be on any public certificate, so an HTTPS origin needs a custom name on the ALB's certificate.

Known-bad

ConfigurationSymptom
Origin domain is the ALB DNS name, HTTPS to the origin502: no certificate can match …amazonaws.com
ALB certificate missing intermediates, or expired502
Internal ALB as an ordinary custom origin (no VPC origin)504: CloudFront can't reach private addresses
VPC origin; ALB security group doesn't admit the service group or prefix list504
VPC origin; outbound NACL blocks ephemeral ports504
VPC without an internet gatewayVPC origin creation fails
Dual-stack VPC origin; security group admits only the IPv4 prefix listIPv6 requests fail (UNVERIFIED symptom)
VPC origin's ALB target group relies on WebSocket health checksALB health checks don't support WebSockets: give the target group an HTTP health path
Public ALB open to 0.0.0.0/0Works, but CloudFront (and WAF at the edge) can be bypassed
ALB returns 502/504 itself (targets unhealthy, keep-alive too short)CloudFront relays it: guides/elb/fix-alb-5xx.md

Which side is wrong?

  • 502 with X-Cache: Error from cloudfront → TLS between CloudFront and the ALB (names, chain), or DNS (NonS3OriginDnsError for a public custom origin).
  • 504 → reachability from CloudFront: security group, NACL, VPC origin state, or an internal ALB without a VPC origin.
  • 5xx that also appears when you call the ALB directly → the ALB or its targets.

Read this document as markdown — the same bytes an agent receives.