Repository: envoyproxy/gateway

Issue:
docs: Merging BackendTrafficPolicies attached to Gateway and Route
*Description*:
>Describe the issue.

relates to https://github.com/envoyproxy/gateway/issues/1934

[optional *Relevant Links*:]
>Any extra documentation required to understand the issue.


Discussion:
@github-actions: This issue has been automatically marked as stale because it has not had activity in the last 30 days.@github-actions: This issue has been automatically marked as stale because it has not had activity in the last 30 days.

Solution patch:
diff --git a/api/v1alpha1/backend_types.go b/api/v1alpha1/backend_types.go
index ceec90834..3f90209ac 100644
--- a/api/v1alpha1/backend_types.go
+++ b/api/v1alpha1/backend_types.go
@@ -55,6 +55,14 @@ type Backend struct {
 // +kubebuilder:validation:XValidation:rule="(has(self.fqdn) || has(self.ip) || has(self.unix))",message="one of fqdn, ip or unix must be specified"
 // +kubebuilder:validation:XValidation:rule="((has(self.fqdn) && !(has(self.ip) || has(self.unix))) || (has(self.ip) && !(has(self.fqdn) || has(self.unix))) || (has(self.unix) && !(has(self.ip) || has(self.fqdn))))",message="only one of fqdn, ip or unix can be specified"
 type BackendEndpoint struct {
+	// Hostname defines a hostname endpoint.
+	//
+	// +kubebuilder:validation:MinLength=1
+	// +kubebuilder:validation:MaxLength=253
+	// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
+	// +optional
+	Hostname *string `json:"hostname,omitempty"`
+
 	// FQDN defines a FQDN endpoint
 	//
 	// +optional
diff --git a/api/v1alpha1/ext_auth_types.go b/api/v1alpha1/ext_auth_types.go
index d9675462a..0ddb3d8e0 100644
--- a/api/v1alpha1/ext_auth_types.go
+++ b/api/v1alpha1/ext_auth_types.go
@@ -43,6 +43,8 @@ type ExtAuth struct {
 	// the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.
 	// This setting determines whether to prioritize accessibility over strict security in case of authorization service failure.
 	//
+	// If set to true, the External Authorization will also be bypassed if its configuration is invalid.
+	//
 	// +optional
 	// +kubebuilder:default=false
 	FailOpen *bool `json:"failOpen,omitempty"`
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 1b1f6adff..bd7446c23 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -371,6 +371,11 @@ func (in *BackendConnection) DeepCopy() *BackendConnection {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *BackendEndpoint) DeepCopyInto(out *BackendEndpoint) {
 	*out = *in
+	if in.Hostname != nil {
+		in, out := &in.Hostname, &out.Hostname
+		*out = new(string)
+		**out = **in
+	}
 	if in.FQDN != nil {
 		in, out := &in.FQDN, &out.FQDN
 		*out = new(FQDNEndpoint)
diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backends.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backends.yaml
index 3688b15c9..f01176af9 100644
--- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backends.yaml
+++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backends.yaml
@@ -93,6 +93,12 @@ spec:
                       - hostname
                       - port
                       type: object
+                    hostname:
+                      description: Hostname defines a hostname endpoint.
+                      maxLength: 253
+                      minLength: 1
+                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
                     ip:
                       description: IP defines an IP endpoint. Supports both IPv4 and
                         IPv6 addresses.
diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml
index 28e1e710d..cb21ac230 100644
--- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml
+++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml
@@ -541,6 +541,8 @@ spec:
                       Otherwise, if it is set to false or not set (defaulting to false),
                       the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.
                       This setting determines whether to prioritize accessibility over strict security in case of authorization service failure.
+
+                      If set to true, the External Authorization will also be bypassed if its configuration is invalid.
                     type: boolean
                   grpc:
                     description: |-
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
index a821ded07..4d530233a 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
@@ -92,6 +92,12 @@ spec:
                       - hostname
                       - port
                       type: object
+                    hostname:
+                      description: Hostname defines a hostname endpoint.
+                      maxLength: 253
+                      minLength: 1
+                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
                     ip:
                       description: IP defines an IP endpoint. Supports both IPv4 and
                         IPv6 addresses.
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
index 49806f57d..6cd283bac 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
@@ -540,6 +540,8 @@ spec:
                       Otherwise, if it is set to false or not set (defaulting to false),
                       the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.
                       This setting determines whether to prioritize accessibility over strict security in case of authorization service failure.
+
+                      If set to true, the External Authorization will also be bypassed if its configuration is invalid.
                     type: boolean
                   grpc:
                     description: |-
diff --git a/internal/gatewayapi/backend.go b/internal/gatewayapi/backend.go
index 59a3cf5d0..22bc6d13d 100644
--- a/internal/gatewayapi/backend.go
+++ b/internal/gatewayapi/backend.go
@@ -76,27 +76,16 @@ func validateBackend(backend *egv1a1.Backend) status.Error {
 	}
 
 	for _, ep := range backend.Spec.Endpoints {
-		if ep.FQDN != nil {
-			hostname := ep.FQDN.Hostname
-			// must be a valid hostname
-			if errs := validation.IsDNS1123Subdomain(hostname); errs != nil {
-				return status.NewRouteStatusError(
-					fmt.Errorf("hostname %s is not a valid FQDN", hostname),
-					status.RouteReasonInvalidAddress,
-				)
-			}
-			if len(strings.Split(hostname, ".")) < 2 {
-				return status.NewRouteStatusError(
-					fmt.Errorf("hostname %s should be a domain with at least two segments separated by dots", hostname),
-					status.RouteReasonInvalidAddress,
-				)
+		if ep.Hostname != nil {
+			routeErr := validateHostname(*ep.Hostname, "hostname")
+			if routeErr != nil {
+				return routeErr
 			}
-			// IP addresses are not allowed so parsing the hostname as an address needs to fail
-			if _, err := netip.ParseAddr(hostname); err == nil {
-				return status.NewRouteStatusError(
-					fmt.Errorf("hostname %s is an IP address", hostname),
-					status.RouteReasonInvalidAddress,
-				)
+		}
+		if ep.FQDN != nil {
+			routeErr := validateHostname(ep.FQDN.Hostname, "FQDN")
+			if routeErr != nil {
+				return routeErr
 			}
 		} else if ep.IP != nil {
 			ip, err := netip.ParseAddr(ep.IP.Address)
@@ -115,3 +104,28 @@ func validateBackend(backend *egv1a1.Backend) status.Error {
 	}
 	return nil
 }
+
+func validateHostname(hostname, typeName string) *status.RouteStatusError {
+	// must be a valid hostname
+	if errs := validation.IsDNS1123Subdomain(hostname); errs != nil {
+		return status.NewRouteStatusError(
+			fmt.Errorf("hostname %s is not a valid %s", hostname, typeName),
+			status.RouteReasonInvalidAddress,
+		)
+	}
+	if len(strings.Split(hostname, ".")) < 2 {
+		return status.NewRouteStatusError(
+			fmt.Errorf("hostname %s should be a domain with at least two segments separated by dots", hostname),
+			status.RouteReasonInvalidAddress,
+		)
+	}
+	// IP addresses are not allowed, so parsing the hostname as an address needs to fail
+	if _, err := netip.ParseAddr(hostname); err == nil {
+		return status.NewRouteStatusError(
+			fmt.Errorf("hostname %s is an IP address", hostname),
+			status.RouteReasonInvalidAddress,
+		)
+	}
+
+	return nil
+}
diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go
index 3ede5ae98..6b087d7e8 100644
--- a/internal/gatewayapi/listener.go
+++ b/internal/gatewayapi/listener.go
@@ -619,6 +619,10 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *
 				if err != nil {
 					return nil, err
 				}
+				// ALS should always use GRPC protocol. Setting this adds http2 by default to the cluster.
+				for _, setting := range ds {
+					setting.Protocol = ir.GRPC
+				}
 
 				al := &ir.ALSAccessLog{
 					LogName: logName,
@@ -848,7 +852,7 @@ func destinationSettingFromHostAndPort(name, host string, port uint32) []*ir.Des
 			Weight:      ptr.To[uint32](1),
 			Protocol:    ir.GRPC,
 			AddressType: ptr.To(addressType),
-			Endpoints:   []*ir.DestinationEndpoint{ir.NewDestEndpoint(host, port, false, nil)},
+			Endpoints:   []*ir.DestinationEndpoint{ir.NewDestEndpoint(nil, host, port, false, nil)},
 		},
 	}
 }
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index 974f2cebc..1178d3431 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -1539,7 +1539,7 @@ func (t *Translator) processServiceImportDestinationSetting(
 		// Fall back to Service ClusterIP routing
 		backendIps := resources.GetServiceImport(backendNamespace, string(backendRef.Name)).Spec.IPs
 		for _, ip := range backendIps {
-			ep := ir.NewDestEndpoint(ip, uint32(*backendRef.Port), false, nil)
+			ep := ir.NewDestEndpoint(nil, ip, uint32(*backendRef.Port), false, nil)
 			endpoints = append(endpoints, ep)
 		}
 	}
@@ -1586,7 +1586,7 @@ func (t *Translator) processServiceDestinationSetting(
 		endpoints, addrType = getIREndpointsFromEndpointSlices(endpointSlices, servicePort.Name, servicePort.Protocol)
 	} else {
 		// Fall back to Service ClusterIP routing
-		ep := ir.NewDestEndpoint(service.Spec.ClusterIP, uint32(*backendRef.Port), false, nil)
+		ep := ir.NewDestEndpoint(nil, service.Spec.ClusterIP, uint32(*backendRef.Port), false, nil)
 		endpoints = append(endpoints, ep)
 	}
 
@@ -1840,12 +1840,12 @@ func getIREndpointsFromEndpointSlice(endpointSlice *discoveryv1.EndpointSlice, p
 				// Drain the endpoint if it is being terminated
 				draining := *conditions.Terminating
 				for _, address := range endpoint.Addresses {
-					ep := ir.NewDestEndpoint(address, uint32(*endpointPort.Port), draining, endpoint.Zone)
+					ep := ir.NewDestEndpoint(nil, address, uint32(*endpointPort.Port), draining, endpoint.Zone)
 					endpoints = append(endpoints, ep)
 				}
 			} else if conditions.Ready == nil || *conditions.Ready {
 				for _, address := range endpoint.Addresses {
-					ep := ir.NewDestEndpoint(address, uint32(*endpointPort.Port), false, endpoint.Zone)
+					ep := ir.NewDestEndpoint(nil, address, uint32(*endpointPort.Port), false, endpoint.Zone)
 					endpoints = append(endpoints, ep)
 				}
 			}
@@ -1980,11 +1980,11 @@ func (t *Translator) processBackendDestinationSetting(
 			ip := net.ParseIP(bep.IP.Address)
 			if ip != nil {
 				addrTypeMap[ir.IP]++
-				irde = ir.NewDestEndpoint(bep.IP.Address, uint32(bep.IP.Port), false, bep.Zone)
+				irde = ir.NewDestEndpoint(bep.Hostname, bep.IP.Address, uint32(bep.IP.Port), false, bep.Zone)
 			}
 		case bep.FQDN != nil:
 			addrTypeMap[ir.FQDN]++
-			irde = ir.NewDestEndpoint(bep.FQDN.Hostname, uint32(bep.FQDN.Port), false, bep.Zone)
+			irde = ir.NewDestEndpoint(bep.Hostname, bep.FQDN.Hostname, uint32(bep.FQDN.Port), false, bep.Zone)
 		case bep.Unix != nil:
 			addrTypeMap[ir.IP]++
 			irde = &ir.DestinationEndpoint{
diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go
index 74edfc95d..5067e3df8 100644
--- a/internal/gatewayapi/securitypolicy.go
+++ b/internal/gatewayapi/securitypolicy.go
@@ -507,11 +507,12 @@ func (t *Translator) translateSecurityPolicyForRoute(
 ) error {
 	// Build IR
 	var (
-		cors          *ir.CORS
-		apiKeyAuth    *ir.APIKeyAuth
-		basicAuth     *ir.BasicAuth
-		authorization *ir.Authorization
-		err, errs     error
+		cors               *ir.CORS
+		apiKeyAuth         *ir.APIKeyAuth
+		basicAuth          *ir.BasicAuth
+		authorization      *ir.Authorization
+		err, errs          error
+		hasNonExtAuthError bool
 	)
 
 	if policy.Spec.CORS != nil {
@@ -538,10 +539,13 @@ func (t *Translator) translateSecurityPolicyForRoute(
 
 	if policy.Spec.Authorization != nil {
 		if authorization, err = t.buildAuthorization(policy); err != nil {
+			err = perr.WithMessage(err, "Authorization")
 			errs = errors.Join(errs, err)
 		}
 	}
 
+	hasNonExtAuthError = errs != nil
+
 	// Apply IR to all relevant routes
 	prefix := irRoutePrefix(route)
 	parentRefs := GetParentReferences(route)
@@ -553,13 +557,14 @@ func (t *Translator) translateSecurityPolicyForRoute(
 		}
 
 		var extAuth *ir.ExtAuth
+		var extAuthErr error
 		if policy.Spec.ExtAuth != nil {
-			if extAuth, err = t.buildExtAuth(
+			if extAuth, extAuthErr = t.buildExtAuth(
 				policy,
 				resources,
-				gtwCtx.envoyProxy); err != nil {
-				err = perr.WithMessage(err, "ExtAuth")
-				errs = errors.Join(errs, err)
+				gtwCtx.envoyProxy); extAuthErr != nil {
+				extAuthErr = perr.WithMessage(extAuthErr, "ExtAuth")
+				errs = errors.Join(errs, extAuthErr)
 			}
 		}
 
@@ -571,6 +576,7 @@ func (t *Translator) translateSecurityPolicyForRoute(
 				gtwCtx.envoyProxy); err != nil {
 				err = perr.WithMessage(err, "OIDC")
 				errs = errors.Join(errs, err)
+				hasNonExtAuthError = true
 			}
 		}
 
@@ -582,6 +588,7 @@ func (t *Translator) translateSecurityPolicyForRoute(
 				gtwCtx.envoyProxy); err != nil {
 				err = perr.WithMessage(err, "JWT")
 				errs = errors.Join(errs, err)
+				hasNonExtAuthError = true
 			}
 		}
 
@@ -601,9 +608,15 @@ func (t *Translator) translateSecurityPolicyForRoute(
 							Authorization: authorization,
 						}
 						if errs != nil {
-							// Return a 500 direct response to avoid unauthorized access
-							r.DirectResponse = &ir.CustomResponse{
-								StatusCode: ptr.To(uint32(500)),
+							// If there is only error for ext auth and ext auth is set to fail open, then skip the ext auth
+							// and allow the request to go through.
+							// Otherwise, return a 500 direct response to avoid unauthorized access.
+							shouldFailOpen := extAuthErr != nil && !hasNonExtAuthError && ptr.Deref(policy.Spec.ExtAuth.FailOpen, false)
+							if !shouldFailOpen {
+								// Return a 500 direct response to avoid unauthorized access
+								r.DirectResponse = &ir.CustomResponse{
+									StatusCode: ptr.To(uint32(500)),
+								}
 							}
 						}
 					}
@@ -623,14 +636,15 @@ func (t *Translator) translateSecurityPolicyForGateway(
 ) error {
 	// Build IR
 	var (
-		cors          *ir.CORS
-		jwt           *ir.JWT
-		oidc          *ir.OIDC
-		apiKeyAuth    *ir.APIKeyAuth
-		basicAuth     *ir.BasicAuth
-		extAuth       *ir.ExtAuth
-		authorization *ir.Authorization
-		err, errs     error
+		cors                  *ir.CORS
+		jwt                   *ir.JWT
+		oidc                  *ir.OIDC
+		apiKeyAuth            *ir.APIKeyAuth
+		basicAuth             *ir.BasicAuth
+		extAuth               *ir.ExtAuth
+		authorization         *ir.Authorization
+		extAuthErr, err, errs error
+		hasNonExtAuthError    bool
 	)
 
 	if policy.Spec.CORS != nil {
@@ -675,21 +689,24 @@ func (t *Translator) translateSecurityPolicyForGateway(
 		}
 	}
 
-	if policy.Spec.ExtAuth != nil {
-		if extAuth, err = t.buildExtAuth(
-			policy,
-			resources,
-			gateway.envoyProxy); err != nil {
-			err = perr.WithMessage(err, "ExtAuth")
+	if policy.Spec.Authorization != nil {
+		if authorization, err = t.buildAuthorization(policy); err != nil {
 			errs = errors.Join(errs, err)
 		}
 	}
 
-	if policy.Spec.Authorization != nil {
-		if authorization, err = t.buildAuthorization(policy); err != nil {
-			errs = errors.Join(errs, err)
+	hasNonExtAuthError = errs != nil
+
+	if policy.Spec.ExtAuth != nil {
+		if extAuth, extAuthErr = t.buildExtAuth(
+			policy,
+			resources,
+			gateway.envoyProxy); extAuthErr != nil {
+			extAuthErr = perr.WithMessage(extAuthErr, "ExtAuth")
+			errs = errors.Join(errs, extAuthErr)
 		}
 	}
+
 	// Apply IR to all the routes within the specific Gateway that originated
 	// from the gateway to which this security policy was attached.
 	// If the feature is already set, then skip it, since it must have be
@@ -731,9 +748,14 @@ func (t *Translator) translateSecurityPolicyForGateway(
 				Authorization: authorization,
 			}
 			if errs != nil {
-				// Return a 500 direct response to avoid unauthorized access
-				r.DirectResponse = &ir.CustomResponse{
-					StatusCode: ptr.To(uint32(500)),
+				// If there is only error for ext auth and ext auth is set to fail open, then skip the ext auth
+				// and allow the request to go through.
+				// Otherwise, return a 500 direct response to avoid unauthorized access.
+				shouldFailOpen := extAuthErr != nil && !hasNonExtAuthError && ptr.Deref(policy.Spec.ExtAuth.FailOpen, false)
+				if !shouldFailOpen {
+					r.DirectResponse = &ir.CustomResponse{
+						StatusCode: ptr.To(uint32(500)),
+					}
 				}
 			}
 		}
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 28c448212..e5ffefc02 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -1683,6 +1683,8 @@ const (
 // DestinationEndpoint holds the endpoint details associated with the destination
 // +kubebuilder:object:generate=true
 type DestinationEndpoint struct {
+	// Hostname refers to the endpoint's hostname
+	Hostname *string `json:"hostname,omitempty" yaml:"hostname,omitempty"`
 	// Host refers to the FQDN or IP address of the backend service.
 	Host string `json:"host" yaml:"host"`
 	// Port on the service to forward the request to.
@@ -1724,8 +1726,9 @@ func (d DestinationEndpoint) Validate() error {
 }
 
 // NewDestEndpoint creates a new DestinationEndpoint.
-func NewDestEndpoint(host string, port uint32, draining bool, zone *string) *DestinationEndpoint {
+func NewDestEndpoint(hostname *string, host string, port uint32, draining bool, zone *string) *DestinationEndpoint {
 	return &DestinationEndpoint{
+		Hostname: hostname,
 		Host:     host,
 		Port:     port,
 		Draining: draining,
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index 6cdbf90c9..b7a3a4486 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -829,6 +829,11 @@ func (in *DNS) DeepCopy() *DNS {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *DestinationEndpoint) DeepCopyInto(out *DestinationEndpoint) {
 	*out = *in
+	if in.Hostname != nil {
+		in, out := &in.Hostname, &out.Hostname
+		*out = new(string)
+		**out = **in
+	}
 	if in.Path != nil {
 		in, out := &in.Path, &out.Path
 		*out = new(string)
diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go
index 3d32977de..1166229e8 100644
--- a/internal/xds/translator/cluster.go
+++ b/internal/xds/translator/cluster.go
@@ -666,7 +666,8 @@ func buildZonalLocalities(metadata *corev3.Metadata, ds *ir.DestinationSetting)
 			Metadata: metadata,
 			HostIdentifier: &endpointv3.LbEndpoint_Endpoint{
 				Endpoint: &endpointv3.Endpoint{
-					Address: buildAddress(irEp),
+					Hostname: ptr.Deref(irEp.Hostname, ""),
+					Address:  buildAddress(irEp),
 				},
 			},
 			LoadBalancingWeight: wrapperspb.UInt32(1),
@@ -708,7 +709,8 @@ func buildWeightedLocalities(metadata *corev3.Metadata, ds *ir.DestinationSettin
 			Metadata: metadata,
 			HostIdentifier: &endpointv3.LbEndpoint_Endpoint{
 				Endpoint: &endpointv3.Endpoint{
-					Address: buildAddress(irEp),
+					Hostname: ptr.Deref(irEp.Hostname, ""),
+					Address:  buildAddress(irEp),
 				},
 			},
 			HealthStatus: healthStatus,
diff --git a/internal/xds/translator/globalresources.go b/internal/xds/translator/globalresources.go
index 0cb59c5f4..1ddb9e3b5 100644
--- a/internal/xds/translator/globalresources.go
+++ b/internal/xds/translator/globalresources.go
@@ -83,7 +83,7 @@ func (t *Translator) createRateLimitServiceCluster(tCtx *types.ResourceVersionTa
 	ds := &ir.DestinationSetting{
 		Weight:    ptr.To[uint32](1),
 		Protocol:  ir.GRPC,
-		Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(host, port, false, nil)},
+		Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(nil, host, port, false, nil)},
 		Name:      destinationSettingName(clusterName),
 	}
 
@@ -153,7 +153,7 @@ func (t *Translator) createWasmHTTPServiceCluster(tCtx *types.ResourceVersionTab
 	ds := &ir.DestinationSetting{
 		Weight:    ptr.To[uint32](1),
 		Protocol:  ir.GRPC,
-		Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(wasmHTTPServiceFQDN(t.ControllerNamespace), wasmHTTPServicePort, false, nil)},
+		Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(nil, wasmHTTPServiceFQDN(t.ControllerNamespace), wasmHTTPServicePort, false, nil)},
 		Name:      destinationSettingName(wasmHTTPServiceClusterName),
 	}
 
diff --git a/internal/xds/translator/oidc.go b/internal/xds/translator/oidc.go
index 1244250a6..fd5c1bf5a 100644
--- a/internal/xds/translator/oidc.go
+++ b/internal/xds/translator/oidc.go
@@ -474,7 +474,7 @@ func createOAuth2TokenEndpointCluster(tCtx *types.ResourceVersionTable,
 	ds = &ir.DestinationSetting{
 		Weight: ptr.To[uint32](1),
 		Endpoints: []*ir.DestinationEndpoint{
-			ir.NewDestEndpoint(cluster.hostname, cluster.port, false, nil),
+			ir.NewDestEndpoint(nil, cluster.hostname, cluster.port, false, nil),
 		},
 		Name: destinationSettingName(cluster.name),
 	}
diff --git a/internal/xds/translator/utils.go b/internal/xds/translator/utils.go
index 5f6c527e7..7220feab2 100644
--- a/internal/xds/translator/utils.go
+++ b/internal/xds/translator/utils.go
@@ -186,7 +186,7 @@ func addClusterFromURL(url string, tCtx *types.ResourceVersionTable) error {
 
 	ds = &ir.DestinationSetting{
 		Weight:    ptr.To[uint32](1),
-		Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(uc.hostname, uc.port, false, nil)},
+		Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint(nil, uc.hostname, uc.port, false, nil)},
 		Name:      destinationSettingName(uc.name),
 	}
 
diff --git a/release-notes/current.yaml b/release-notes/current.yaml
index 54b463b1c..4aaba48f1 100644
--- a/release-notes/current.yaml
+++ b/release-notes/current.yaml
@@ -36,7 +36,7 @@ new features: |
   Added support for SecurityPolicy and EnvoyExtensionPolicy to target ServiceImport via BackendRefs.
   Introduce validation strictness levels for Lua scripts in EnvoyExtensionPolicies.
   Added metric `watchable_publish_total` counting store events in watchable message queues.
-
+  Accessloggers of type ALS now have http2 enabled on the cluster by default.
 
 bug fixes: |
   Handle integer zone annotation values
@@ -53,6 +53,7 @@ bug fixes: |
   Fixed validation errors when the rateLimit url for Redis in the EnvoyGateway API includes multiple comma separated hosts.
   Fixes addresses in status of DualStack NodePort Gateways.
   Fixed issue that not able to override the prometheus annotation in EnvoyProxy CRD.
+  Skipped ExtProc, Wasm, and ExtAuth when they are configured FailOpen and the configuration is invalid, e.g. missing backendRefs or invalid port.
   Fixed issue that failed to update policy status when there are more than 16 ancestors.
 
 # Enhancements that improve performance.



Test patch:
diff --git a/internal/gatewayapi/route_test.go b/internal/gatewayapi/route_test.go
index 131e67879..31de02fd1 100644
--- a/internal/gatewayapi/route_test.go
+++ b/internal/gatewayapi/route_test.go
@@ -232,6 +232,7 @@ func TestGetIREndpointsFromEndpointSlices(t *testing.T) {
 
 func TestValidateDestinationSettings(t *testing.T) {
 	svcKind := gwapiv1.Kind(resource.KindService)
+	hostname := "www.gateway-test.com"
 
 	tests := []struct {
 		name                    string
@@ -262,6 +263,16 @@ func TestValidateDestinationSettings(t *testing.T) {
 			kind:                    &svcKind,
 			wantErr:                 false,
 		},
+		{
+			name: "normal service allowed with hostname",
+			ds: &ir.DestinationSetting{
+				Name:      "normal with hostname",
+				Endpoints: []*ir.DestinationEndpoint{{Hostname: &hostname, Host: "10.0.0.1"}},
+			},
+			endpointRoutingDisabled: true,
+			kind:                    &svcKind,
+			wantErr:                 false,
+		},
 		{
 			name: "mixed address type rejected when EndpointSlice routing",
 			ds: &ir.DestinationSetting{
diff --git a/internal/gatewayapi/testdata/accesslog-als-grpc.in.yaml b/internal/gatewayapi/testdata/accesslog-als-grpc.in.yaml
new file mode 100644
index 000000000..2c354193a
--- /dev/null
+++ b/internal/gatewayapi/testdata/accesslog-als-grpc.in.yaml
@@ -0,0 +1,46 @@
+envoyProxyForGatewayClass:
+  apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: EnvoyProxy
+  metadata:
+    namespace: envoy-gateway-system
+    name: als-backend
+  spec:
+    telemetry:
+      accessLog:
+        settings:
+          - sinks:
+              - type: ALS
+                als:
+                  backendRefs:
+                    - name: access-logger
+                      namespace: default
+                      port: 50051
+                  type: HTTP
+gateways:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: Gateway
+    metadata:
+      namespace: envoy-gateway
+      name: gateway-1
+    spec:
+      gatewayClassName: envoy-gateway-class
+      listeners:
+        - name: http
+          protocol: HTTP
+          port: 80
+          allowedRoutes:
+            namespaces:
+              from: Same
+services:
+  - apiVersion: v1
+    kind: Service
+    metadata:
+      name: access-logger
+      namespace: default
+    spec:
+      clusterIP: 10.11.12.13
+      ports:
+        - port: 50051
+          name: grpc
+          protocol: TCP
+          targetPort: 50051
diff --git a/internal/gatewayapi/testdata/accesslog-als-grpc.out.yaml b/internal/gatewayapi/testdata/accesslog-als-grpc.out.yaml
new file mode 100644
index 000000000..efe420cc8
--- /dev/null
+++ b/internal/gatewayapi/testdata/accesslog-als-grpc.out.yaml
@@ -0,0 +1,122 @@
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-1
+    namespace: envoy-gateway
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        namespaces:
+          from: Same
+      name: http
+      port: 80
+      protocol: HTTP
+  status:
+    listeners:
+    - attachedRoutes: 0
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: http
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+infraIR:
+  envoy-gateway/gateway-1:
+    proxy:
+      config:
+        apiVersion: gateway.envoyproxy.io/v1alpha1
+        kind: EnvoyProxy
+        metadata:
+          creationTimestamp: null
+          name: als-backend
+          namespace: envoy-gateway-system
+        spec:
+          logging: {}
+          telemetry:
+            accessLog:
+              settings:
+              - sinks:
+                - als:
+                    backendRefs:
+                    - name: access-logger
+                      namespace: default
+                      port: 50051
+                    type: HTTP
+                  type: ALS
+        status: {}
+      listeners:
+      - address: null
+        name: envoy-gateway/gateway-1/http
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-1
+          gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+        ownerReference:
+          kind: GatewayClass
+          name: envoy-gateway-class
+      name: envoy-gateway/gateway-1
+      namespace: envoy-gateway-system
+xdsIR:
+  envoy-gateway/gateway-1:
+    accessLog:
+      als:
+      - destination:
+          metadata:
+            kind: EnvoyProxy
+            name: als-backend
+            namespace: envoy-gateway-system
+          name: accesslog_als_0_0
+          settings:
+          - metadata:
+              kind: Service
+              name: access-logger
+              namespace: default
+              sectionName: "50051"
+            name: accesslog_als_0_0/backend/-1
+            protocol: GRPC
+        name: envoy-gateway-system/als-backend
+        type: HTTP
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+      name: envoy-gateway/gateway-1/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+    readyListener:
+      address: 0.0.0.0
+      ipFamily: IPv4
+      path: /ready
+      port: 19003
diff --git a/internal/gatewayapi/testdata/backend-with-hostname.in.yaml b/internal/gatewayapi/testdata/backend-with-hostname.in.yaml
new file mode 100644
index 000000000..df2e8cfff
--- /dev/null
+++ b/internal/gatewayapi/testdata/backend-with-hostname.in.yaml
@@ -0,0 +1,60 @@
+gateways:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: Gateway
+    metadata:
+      namespace: envoy-gateway
+      name: gateway-1
+    spec:
+      gatewayClassName: envoy-gateway-class
+      listeners:
+        - name: http
+          protocol: HTTP
+          port: 80
+          allowedRoutes:
+            namespaces:
+              from: All
+httpRoutes:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      namespace: default
+      name: httproute-1
+    spec:
+      parentRefs:
+        - namespace: envoy-gateway
+          name: gateway-1
+      rules:
+        - matches:
+            - path:
+                value: "/"
+          backendRefs:
+            - group: gateway.envoyproxy.io
+              kind: Backend
+              name: backend-1
+            - group: gateway.envoyproxy.io
+              kind: Backend
+              name: backend-2
+backends:
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: Backend
+    metadata:
+      name: backend-1
+      namespace: default
+    spec:
+      endpoints:
+        - hostname: "example.com"
+          ip:
+            address: 1.1.1.1
+            port: 3001
+          zone: zone1
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: Backend
+    metadata:
+      name: backend-2
+      namespace: default
+    spec:
+      endpoints:
+        - ip:
+            address: 2.2.2.2
+            port: 3001
+          zone: zone2
diff --git a/internal/gatewayapi/testdata/backend-with-hostname.out.yaml b/internal/gatewayapi/testdata/backend-with-hostname.out.yaml
new file mode 100644
index 000000000..de6179b09
--- /dev/null
+++ b/internal/gatewayapi/testdata/backend-with-hostname.out.yaml
@@ -0,0 +1,209 @@
+backends:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: Backend
+  metadata:
+    creationTimestamp: null
+    name: backend-1
+    namespace: default
+  spec:
+    endpoints:
+    - hostname: example.com
+      ip:
+        address: 1.1.1.1
+        port: 3001
+      zone: zone1
+  status:
+    conditions:
+    - lastTransitionTime: null
+      message: The Backend was accepted
+      reason: Accepted
+      status: "True"
+      type: Accepted
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: Backend
+  metadata:
+    creationTimestamp: null
+    name: backend-2
+    namespace: default
+  spec:
+    endpoints:
+    - ip:
+        address: 2.2.2.2
+        port: 3001
+      zone: zone2
+  status:
+    conditions:
+    - lastTransitionTime: null
+      message: The Backend was accepted
+      reason: Accepted
+      status: "True"
+      type: Accepted
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-1
+    namespace: envoy-gateway
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        namespaces:
+          from: All
+      name: http
+      port: 80
+      protocol: HTTP
+  status:
+    listeners:
+    - attachedRoutes: 1
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: http
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-1
+    namespace: default
+  spec:
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+    rules:
+    - backendRefs:
+      - group: gateway.envoyproxy.io
+        kind: Backend
+        name: backend-1
+      - group: gateway.envoyproxy.io
+        kind: Backend
+        name: backend-2
+      matches:
+      - path:
+          value: /
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+infraIR:
+  envoy-gateway/gateway-1:
+    proxy:
+      listeners:
+      - address: null
+        name: envoy-gateway/gateway-1/http
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-1
+          gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+        ownerReference:
+          kind: GatewayClass
+          name: envoy-gateway-class
+      name: envoy-gateway/gateway-1
+      namespace: envoy-gateway-system
+xdsIR:
+  envoy-gateway/gateway-1:
+    accessLog:
+      json:
+      - path: /dev/stdout
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+      name: envoy-gateway/gateway-1/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          metadata:
+            kind: HTTPRoute
+            name: httproute-1
+            namespace: default
+          name: httproute/default/httproute-1/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 1.1.1.1
+              hostname: example.com
+              port: 3001
+              zone: zone1
+            metadata:
+              kind: Backend
+              name: backend-1
+              namespace: default
+            name: httproute/default/httproute-1/rule/0/backend/0
+            protocol: HTTP
+            weight: 1
+          - addressType: IP
+            endpoints:
+            - host: 2.2.2.2
+              port: 3001
+              zone: zone2
+            metadata:
+              kind: Backend
+              name: backend-2
+              namespace: default
+            name: httproute/default/httproute-1/rule/0/backend/1
+            protocol: HTTP
+            weight: 1
+        hostname: '*'
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-1
+          namespace: default
+        name: httproute/default/httproute-1/rule/0/match/0/*
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /
+    readyListener:
+      address: 0.0.0.0
+      ipFamily: IPv4
+      path: /ready
+      port: 19003
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.in.yaml
index e47a1b0f5..de74b2764 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.in.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.in.yaml
@@ -13,12 +13,40 @@ gateways:
           allowedRoutes:
             namespaces:
               from: All
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: Gateway
+    metadata:
+      namespace: default
+      name: gateway-2
+    spec:
+      gatewayClassName: envoy-gateway-class
+      listeners:
+        - name: http
+          protocol: HTTP
+          port: 80
+          allowedRoutes:
+            namespaces:
+              from: All
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: Gateway
+    metadata:
+      namespace: default
+      name: gateway-3
+    spec:
+      gatewayClassName: envoy-gateway-class
+      listeners:
+        - name: http
+          protocol: HTTP
+          port: 80
+          allowedRoutes:
+            namespaces:
+              from: All
 httpRoutes:
   - apiVersion: gateway.networking.k8s.io/v1
     kind: HTTPRoute
     metadata:
       namespace: default
-      name: httproute-1
+      name: httproute-1     # should return 500 because the ext auth in the attached policy is fail close.
     spec:
       hostnames:
         - www.foo.com
@@ -33,17 +61,93 @@ httpRoutes:
           backendRefs:
             - name: service-1
               port: 8080
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      namespace: default
+      name: httproute-2     # should not return 500 because the ext auth in the attached policy is fail open.
+    spec:
+      hostnames:
+        - www.bar.com
+      parentRefs:
+        - namespace: default
+          name: gateway-1
+          sectionName: http
+      rules:
+        - matches:
+            - path:
+                value: /bar
+          backendRefs:
+            - name: service-1
+              port: 8080
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      namespace: default
+      name: httproute-3     # should return 500 because the ext auth is invalid with failopen, and the basic auth is invalid.
+    spec:
+      hostnames:
+        - www.baz.com
+      parentRefs:
+        - namespace: default
+          name: gateway-1
+          sectionName: http
+      rules:
+        - matches:
+            - path:
+                value: /baz
+          backendRefs:
+            - name: service-1
+              port: 8080
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      namespace: default
+      name: httproute-4     # should not return 500 because the ext auth is invalid with failopen.
+    spec:
+      hostnames:
+        - www.qux.com
+      parentRefs:
+        - namespace: default
+          name: gateway-2
+          sectionName: http
+      rules:
+        - matches:
+            - path:
+                value: /qux
+          backendRefs:
+            - name: service-1
+              port: 8080
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      namespace: default
+      name: httproute-5     # should return 500 because the ext auth is invalid with failopen, and the basic auth is invalid.
+    spec:
+      hostnames:
+        - www.quux.com
+      parentRefs:
+        - namespace: default
+          name: gateway-3
+          sectionName: http
+      rules:
+        - matches:
+            - path:
+                value: /quux
+          backendRefs:
+            - name: service-1
+              port: 8080
 securityPolicies:
   - apiVersion: gateway.envoyproxy.io/v1alpha1
     kind: SecurityPolicy
     metadata:
       namespace: default
-      name: policy-for-gateway
+      name: policy-for-httproute-1
     spec:
       targetRef:
         group: gateway.networking.k8s.io
-        kind: Gateway
-        name: gateway-1
+        kind: HTTPRoute
+        name: httproute-1
       extAuth:
         http:
           backendRefs:
@@ -54,3 +158,89 @@ securityPolicies:
             - header1
             - header2
         failOpen: false
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: SecurityPolicy
+    metadata:
+      namespace: default
+      name: policy-for-httproute-2
+    spec:
+      targetRef:
+        group: gateway.networking.k8s.io
+        kind: HTTPRoute
+        name: httproute-2
+      extAuth:
+        http:
+          backendRefs:
+            - name: http-backend
+              namespace: default
+              port: 80
+          headersToBackend:
+            - header1
+            - header2
+        failOpen: true
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: SecurityPolicy
+    metadata:
+      namespace: default
+      name: policy-for-httproute-3
+    spec:
+      targetRef:
+        group: gateway.networking.k8s.io
+        kind: HTTPRoute
+        name: httproute-3
+      basicAuth:
+        users:
+          name: "users-secret1"
+      extAuth:
+        http:
+          backendRefs:
+            - name: http-backend
+              namespace: default
+              port: 80
+          headersToBackend:
+            - header1
+            - header2
+        failOpen: true
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: SecurityPolicy
+    metadata:
+      namespace: default
+      name: policy-for-gateway-2
+    spec:
+      targetRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-2
+      extAuth:
+        http:
+          backendRefs:
+            - name: http-backend
+              namespace: default
+              port: 80
+          headersToBackend:
+            - header1
+            - header2
+        failOpen: true
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: SecurityPolicy
+    metadata:
+      namespace: default
+      name: policy-for-gateway-3
+    spec:
+      targetRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-3
+      basicAuth:
+        users:
+          name: "users-secret1"
+      extAuth:
+        http:
+          backendRefs:
+            - name: http-backend
+              namespace: default
+              port: 80
+          headersToBackend:
+            - header1
+            - header2
+        failOpen: true
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml
index 8405eaf3f..07b58402a 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml
@@ -14,6 +14,86 @@ gateways:
       name: http
       port: 80
       protocol: HTTP
+  status:
+    listeners:
+    - attachedRoutes: 3
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: http
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-2
+    namespace: default
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        namespaces:
+          from: All
+      name: http
+      port: 80
+      protocol: HTTP
+  status:
+    listeners:
+    - attachedRoutes: 1
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: http
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-3
+    namespace: default
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        namespaces:
+          from: All
+      name: http
+      port: 80
+      protocol: HTTP
   status:
     listeners:
     - attachedRoutes: 1
@@ -78,6 +158,158 @@ httpRoutes:
         name: gateway-1
         namespace: default
         sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-2
+    namespace: default
+  spec:
+    hostnames:
+    - www.bar.com
+    parentRefs:
+    - name: gateway-1
+      namespace: default
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /bar
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: default
+        sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - www.baz.com
+    parentRefs:
+    - name: gateway-1
+      namespace: default
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /baz
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: default
+        sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-4
+    namespace: default
+  spec:
+    hostnames:
+    - www.qux.com
+    parentRefs:
+    - name: gateway-2
+      namespace: default
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /qux
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-2
+        namespace: default
+        sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-5
+    namespace: default
+  spec:
+    hostnames:
+    - www.quux.com
+    parentRefs:
+    - name: gateway-3
+      namespace: default
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /quux
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-3
+        namespace: default
+        sectionName: http
 infraIR:
   default/gateway-1:
     proxy:
@@ -98,12 +330,50 @@ infraIR:
           name: envoy-gateway-class
       name: default/gateway-1
       namespace: envoy-gateway-system
+  default/gateway-2:
+    proxy:
+      listeners:
+      - address: null
+        name: default/gateway-2/http
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-2
+          gateway.envoyproxy.io/owning-gateway-namespace: default
+        ownerReference:
+          kind: GatewayClass
+          name: envoy-gateway-class
+      name: default/gateway-2
+      namespace: envoy-gateway-system
+  default/gateway-3:
+    proxy:
+      listeners:
+      - address: null
+        name: default/gateway-3/http
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-3
+          gateway.envoyproxy.io/owning-gateway-namespace: default
+        ownerReference:
+          kind: GatewayClass
+          name: envoy-gateway-class
+      name: default/gateway-3
+      namespace: envoy-gateway-system
 securityPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: SecurityPolicy
   metadata:
     creationTimestamp: null
-    name: policy-for-gateway
+    name: policy-for-httproute-1
     namespace: default
   spec:
     extAuth:
@@ -118,8 +388,8 @@ securityPolicies:
         - header2
     targetRef:
       group: gateway.networking.k8s.io
-      kind: Gateway
-      name: gateway-1
+      kind: HTTPRoute
+      name: httproute-1
   status:
     ancestors:
     - ancestorRef:
@@ -127,6 +397,7 @@ securityPolicies:
         kind: Gateway
         name: gateway-1
         namespace: default
+        sectionName: http
       conditions:
       - lastTransitionTime: null
         message: 'ExtAuth: service default/http-backend not found.'
@@ -134,6 +405,162 @@ securityPolicies:
         status: "False"
         type: Accepted
       controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: SecurityPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-httproute-2
+    namespace: default
+  spec:
+    extAuth:
+      failOpen: true
+      http:
+        backendRefs:
+        - name: http-backend
+          namespace: default
+          port: 80
+        headersToBackend:
+        - header1
+        - header2
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-2
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-1
+        namespace: default
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: 'ExtAuth: service default/http-backend not found.'
+        reason: Invalid
+        status: "False"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: SecurityPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-httproute-3
+    namespace: default
+  spec:
+    basicAuth:
+      users:
+        group: null
+        kind: null
+        name: users-secret1
+    extAuth:
+      failOpen: true
+      http:
+        backendRefs:
+        - name: http-backend
+          namespace: default
+          port: 80
+        headersToBackend:
+        - header1
+        - header2
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-1
+        namespace: default
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: |-
+          BasicAuth: secret default/users-secret1 does not exist
+          ExtAuth: service default/http-backend not found.
+        reason: Invalid
+        status: "False"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: SecurityPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-gateway-2
+    namespace: default
+  spec:
+    extAuth:
+      failOpen: true
+      http:
+        backendRefs:
+        - name: http-backend
+          namespace: default
+          port: 80
+        headersToBackend:
+        - header1
+        - header2
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: Gateway
+      name: gateway-2
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-2
+        namespace: default
+      conditions:
+      - lastTransitionTime: null
+        message: 'ExtAuth: service default/http-backend not found.'
+        reason: Invalid
+        status: "False"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: SecurityPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-gateway-3
+    namespace: default
+  spec:
+    basicAuth:
+      users:
+        group: null
+        kind: null
+        name: users-secret1
+    extAuth:
+      failOpen: true
+      http:
+        backendRefs:
+        - name: http-backend
+          namespace: default
+          port: 80
+        headersToBackend:
+        - header1
+        - header2
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: Gateway
+      name: gateway-3
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-3
+        namespace: default
+      conditions:
+      - lastTransitionTime: null
+        message: |-
+          BasicAuth: secret default/users-secret1 does not exist
+          ExtAuth: service default/http-backend not found.
+        reason: Invalid
+        status: "False"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
 xdsIR:
   default/gateway-1:
     accessLog:
@@ -187,6 +614,180 @@ xdsIR:
           name: ""
           prefix: /foo
         security: {}
+      - destination:
+          metadata:
+            kind: HTTPRoute
+            name: httproute-2
+            namespace: default
+          name: httproute/default/httproute-2/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-1
+              namespace: default
+              sectionName: "8080"
+            name: httproute/default/httproute-2/rule/0/backend/0
+            protocol: HTTP
+            weight: 1
+        hostname: www.bar.com
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-2
+          namespace: default
+        name: httproute/default/httproute-2/rule/0/match/0/www_bar_com
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /bar
+        security: {}
+      - destination:
+          metadata:
+            kind: HTTPRoute
+            name: httproute-3
+            namespace: default
+          name: httproute/default/httproute-3/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-1
+              namespace: default
+              sectionName: "8080"
+            name: httproute/default/httproute-3/rule/0/backend/0
+            protocol: HTTP
+            weight: 1
+        directResponse:
+          statusCode: 500
+        hostname: www.baz.com
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-3
+          namespace: default
+        name: httproute/default/httproute-3/rule/0/match/0/www_baz_com
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /baz
+        security: {}
+    readyListener:
+      address: 0.0.0.0
+      ipFamily: IPv4
+      path: /ready
+      port: 19003
+  default/gateway-2:
+    accessLog:
+      json:
+      - path: /dev/stdout
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-2
+        namespace: default
+        sectionName: http
+      name: default/gateway-2/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          metadata:
+            kind: HTTPRoute
+            name: httproute-4
+            namespace: default
+          name: httproute/default/httproute-4/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-1
+              namespace: default
+              sectionName: "8080"
+            name: httproute/default/httproute-4/rule/0/backend/0
+            protocol: HTTP
+            weight: 1
+        hostname: www.qux.com
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-4
+          namespace: default
+        name: httproute/default/httproute-4/rule/0/match/0/www_qux_com
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /qux
+        security: {}
+    readyListener:
+      address: 0.0.0.0
+      ipFamily: IPv4
+      path: /ready
+      port: 19003
+  default/gateway-3:
+    accessLog:
+      json:
+      - path: /dev/stdout
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-3
+        namespace: default
+        sectionName: http
+      name: default/gateway-3/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          metadata:
+            kind: HTTPRoute
+            name: httproute-5
+            namespace: default
+          name: httproute/default/httproute-5/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-1
+              namespace: default
+              sectionName: "8080"
+            name: httproute/default/httproute-5/rule/0/backend/0
+            protocol: HTTP
+            weight: 1
+        directResponse:
+          statusCode: 500
+        hostname: www.quux.com
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-5
+          namespace: default
+        name: httproute/default/httproute-5/rule/0/match/0/www_quux_com
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /quux
+        security: {}
     readyListener:
       address: 0.0.0.0
       ipFamily: IPv4
diff --git a/internal/xds/translator/testdata/in/extension-xds-ir/http-route.yaml b/internal/xds/translator/testdata/in/extension-xds-ir/http-route.yaml
index 2f6371401..4aa6680eb 100644
--- a/internal/xds/translator/testdata/in/extension-xds-ir/http-route.yaml
+++ b/internal/xds/translator/testdata/in/extension-xds-ir/http-route.yaml
@@ -24,6 +24,7 @@ http:
       name: "first-route-dest"
       settings:
       - endpoints:
-        - host: "1.2.3.4"
+        - hostname: "example.com"
+          host: "1.2.3.4"
           port: 50000
         name: "first-route-dest/backend/0"
diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.endpoints.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.endpoints.yaml
index 3b3f2d090..d01640140 100644
--- a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.endpoints.yaml
+++ b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.endpoints.yaml
@@ -6,6 +6,7 @@
           socketAddress:
             address: 1.2.3.4
             portValue: 50000
+        hostname: example.com
       loadBalancingWeight: 1
     loadBalancingWeight: 1
     locality:
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index e7bd043e1..9dd5ecf16 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -357,6 +357,7 @@ _Appears in:_
 
 | Field | Type | Required | Default | Description |
 | ---   | ---  | ---      | ---     | ---         |
+| `hostname` | _string_ |  false  |  | Hostname defines a hostname endpoint. |
 | `fqdn` | _[FQDNEndpoint](#fqdnendpoint)_ |  false  |  | FQDN defines a FQDN endpoint |
 | `ip` | _[IPEndpoint](#ipendpoint)_ |  false  |  | IP defines an IP endpoint. Supports both IPv4 and IPv6 addresses. |
 | `unix` | _[UnixSocket](#unixsocket)_ |  false  |  | Unix defines the unix domain socket endpoint |
@@ -1683,7 +1684,7 @@ _Appears in:_
 | `http` | _[HTTPExtAuthService](#httpextauthservice)_ |  true  |  | HTTP defines the HTTP External Authorization service.<br />Either GRPCService or HTTPService must be specified,<br />and only one of them can be provided. |
 | `headersToExtAuth` | _string array_ |  false  |  | HeadersToExtAuth defines the client request headers that will be included<br />in the request to the external authorization service.<br />Note: If not specified, the default behavior for gRPC and HTTP external<br />authorization services is different due to backward compatibility reasons.<br />All headers will be included in the check request to a gRPC authorization server.<br />Only the following headers will be included in the check request to an HTTP<br />authorization server: Host, Method, Path, Content-Length, and Authorization.<br />And these headers will always be included to the check request to an HTTP<br />authorization server by default, no matter whether they are specified<br />in HeadersToExtAuth or not. |
 | `bodyToExtAuth` | _[BodyToExtAuth](#bodytoextauth)_ |  false  |  | BodyToExtAuth defines the Body to Ext Auth configuration. |
-| `failOpen` | _boolean_ |  false  | false | FailOpen is a switch used to control the behavior when a response from the External Authorization service cannot be obtained.<br />If FailOpen is set to true, the system allows the traffic to pass through.<br />Otherwise, if it is set to false or not set (defaulting to false),<br />the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.<br />This setting determines whether to prioritize accessibility over strict security in case of authorization service failure. |
+| `failOpen` | _boolean_ |  false  | false | FailOpen is a switch used to control the behavior when a response from the External Authorization service cannot be obtained.<br />If FailOpen is set to true, the system allows the traffic to pass through.<br />Otherwise, if it is set to false or not set (defaulting to false),<br />the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.<br />This setting determines whether to prioritize accessibility over strict security in case of authorization service failure.<br />If set to true, the External Authorization will also be bypassed if its configuration is invalid. |
 | `recomputeRoute` | _boolean_ |  false  |  | RecomputeRoute clears the route cache and recalculates the routing decision.<br />This field must be enabled if the headers added or modified by the ExtAuth are used for<br />route matching decisions. If the recomputation selects a new route, features targeting<br />the new matched route will be applied. |
 
 
@@ -1820,6 +1821,7 @@ _Appears in:_
 
 | Field | Type | Required | Default | Description |
 | ---   | ---  | ---      | ---     | ---         |
+| `hostname` | _string_ |  false  |  | Hostname defines a hostname endpoint. |
 | `fqdn` | _[FQDNEndpoint](#fqdnendpoint)_ |  false  |  | FQDN defines a FQDN endpoint |
 | `ip` | _[IPEndpoint](#ipendpoint)_ |  false  |  | IP defines an IP endpoint. Supports both IPv4 and IPv6 addresses. |
 | `unix` | _[UnixSocket](#unixsocket)_ |  false  |  | Unix defines the unix domain socket endpoint |
diff --git a/site/content/en/latest/tasks/traffic/global-rate-limit.md b/site/content/en/latest/tasks/traffic/global-rate-limit.md
index 63f940b15..8b2ccd193 100644
--- a/site/content/en/latest/tasks/traffic/global-rate-limit.md
+++ b/site/content/en/latest/tasks/traffic/global-rate-limit.md
@@ -1213,6 +1213,225 @@ server: envoy
 
 ```
 
+## Rate Limit Policy Merging
+
+This example demonstrates how to implement a layered rate limiting strategy using BackendTrafficPolicy merging. This approach allows platform teams to set global abuse prevention limits at the Gateway level, while application teams can define more specific rate limits for their individual routes.
+
+In this scenario:
+- **Platform Team**: Manages a Gateway-level BackendTrafficPolicy that applies a global abuse rate limit (100 requests/second) across all traffic
+- **Application Team**: Manages a Route-level BackendTrafficPolicy that applies a more restrictive limit (5 requests/minute) for their specific signup service
+
+The route-level policy uses `mergeType: StrategicMerge` to combine with the gateway-level policy, ensuring both limits are enforced. The global limit acts as an abuse prevention mechanism, while the route-specific limit protects the signup service from overload.
+
+{{< tabpane text=true >}}
+{{% tab header="Apply from stdin" %}}
+
+```shell
+cat <<EOF | kubectl apply -f -
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: global-backendtrafficpolicy
+spec:
+  rateLimit:
+    type: Global
+    global:
+      rules:
+      - clientSelectors:
+        - sourceCIDR:
+            type: Distinct
+            value: 0.0.0.0/0
+        limit:
+          requests: 100
+          unit: Second
+        shared: true
+  targetRefs:
+  - group: gateway.networking.k8s.io
+    kind: Gateway
+    name: eg
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: route-backendtrafficpolicy
+spec:
+  mergeType: StrategicMerge
+  rateLimit:
+    type: Global
+    global:
+      rules:
+      - clientSelectors:
+        - sourceCIDR:
+            type: Distinct
+            value: 0.0.0.0/0
+        limit:
+          requests: 5
+          unit: Minute
+        shared: false
+  targetRefs:
+  - group: gateway.networking.k8s.io
+    kind: HTTPRoute
+    name: signup-service-httproute
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: signup-service-httproute
+spec:
+  parentRefs:
+  - name: eg
+  hostnames:
+  - signup.example
+  rules:
+  - matches:
+    - path:
+        type: PathPrefix
+        value: /signup
+    backendRefs:
+    - group: ""
+      kind: Service
+      name: backend
+      port: 3000
+EOF
+```
+
+{{% /tab %}}
+{{% tab header="Apply from file" %}}
+Save and apply the following resources to your cluster:
+
+```yaml
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: global-backendtrafficpolicy
+spec:
+  rateLimit:
+    type: Global
+    global:
+      rules:
+      - clientSelectors:
+        - sourceCIDR:
+            type: Distinct
+            value: 0.0.0.0/0
+        limit:
+          requests: 100
+          unit: Second
+        shared: true
+  targetRefs:
+  - group: gateway.networking.k8s.io
+    kind: Gateway
+    name: eg
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: route-backendtrafficpolicy
+spec:
+  mergeType: StrategicMerge
+  rateLimit:
+    type: Global
+    global:
+      rules:
+      - clientSelectors:
+        - sourceCIDR:
+            type: Distinct
+            value: 0.0.0.0/0
+        limit:
+          requests: 5
+          unit: Minute
+        shared: false
+  targetRefs:
+  - group: gateway.networking.k8s.io
+    kind: HTTPRoute
+    name: signup-service-httproute
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: signup-service-httproute
+spec:
+  parentRefs:
+  - name: eg
+  hostnames:
+  - signup.example
+  rules:
+  - matches:
+    - path:
+        type: PathPrefix
+        value: /signup
+    backendRefs:
+    - group: ""
+      kind: Service
+      name: backend
+      port: 3000
+```
+
+{{% /tab %}}
+{{< /tabpane >}}
+
+### Key Configuration Details
+
+- **Gateway-level Policy**: Uses `shared: true` to create a shared rate limit bucket that applies across all routes in the Gateway
+- **Route-level Policy**: Uses `shared: false` to create a dedicated rate limit bucket for this specific route
+- **Merge Type**: The `mergeType: StrategicMerge` field enables the route policy to merge with the gateway policy rather than override it
+
+### Testing the Merged Rate Limits
+
+Let's verify that both rate limits are enforced. The signup service should be limited to 5 requests per minute, but also subject to the global 100 requests/second abuse limit.
+
+First, let's test the route-specific limit by sending 6 requests within a minute:
+
+```shell
+for i in {1..6}; do curl -I --header "Host: signup.example" http://${GATEWAY_HOST}/signup ; sleep 1; done
+```
+
+You should see the first 5 requests succeed and the 6th request receive a `429 Too Many Requests` response:
+
+```console
+HTTP/1.1 200 OK
+content-type: application/json
+x-content-type-options: nosniff
+date: Wed, 08 Feb 2023 02:33:31 GMT
+content-length: 460
+x-envoy-upstream-service-time: 4
+server: envoy
+
+HTTP/1.1 200 OK
+content-type: application/json
+x-content-type-options: nosniff
+date: Wed, 08 Feb 2023 02:33:32 GMT
+content-length: 460
+x-envoy-upstream-service-time: 2
+server: envoy
+
+...
+
+HTTP/1.1 429 Too Many Requests
+x-envoy-ratelimited: true
+date: Wed, 08 Feb 2023 02:33:36 GMT
+server: envoy
+transfer-encoding: chunked
+```
+
+The global abuse limit would activate if traffic across all routes in the Gateway exceeds 100 requests/second, providing an additional layer of protection managed by the platform team.
+
+### Use Cases and Team Responsibilities
+
+**Platform Team Responsibilities:**
+- Define Gateway-level policies with global abuse rate limits
+- Set reasonable baseline protections that apply to all applications
+- Use `shared: true` for limits that should be enforced across multiple routes
+- Monitor and adjust global limits based on infrastructure capacity
+
+**Application Team Responsibilities:**  
+- Define Route-level policies with application-specific rate limits
+- Use `mergeType: StrategicMerge` to combine with platform policies
+- Set `shared: false` for limits specific to their application's requirements
+- Implement rate limits that protect their specific service from overload
+
+This layered approach ensures both infrastructure protection and application-specific controls work together effectively.
+
 ### (Optional) Editing Kubernetes Resources settings for the Rate Limit Service
 
 * The default installation of Envoy Gateway installs a default [EnvoyGateway][] configuration and provides the initial rate
diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml
index 80f084500..cf3656837 100644
--- a/test/helm/gateway-crds-helm/all.out.yaml
+++ b/test/helm/gateway-crds-helm/all.out.yaml
@@ -17405,6 +17405,12 @@ spec:
                       - hostname
                       - port
                       type: object
+                    hostname:
+                      description: Hostname defines a hostname endpoint.
+                      maxLength: 253
+                      minLength: 1
+                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
                     ip:
                       description: IP defines an IP endpoint. Supports both IPv4 and
                         IPv6 addresses.
@@ -39653,6 +39659,8 @@ spec:
                       Otherwise, if it is set to false or not set (defaulting to false),
                       the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.
                       This setting determines whether to prioritize accessibility over strict security in case of authorization service failure.
+
+                      If set to true, the External Authorization will also be bypassed if its configuration is invalid.
                     type: boolean
                   grpc:
                     description: |-
diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
index 428147cf7..6dff81bf3 100644
--- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
+++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
@@ -93,6 +93,12 @@ spec:
                       - hostname
                       - port
                       type: object
+                    hostname:
+                      description: Hostname defines a hostname endpoint.
+                      maxLength: 253
+                      minLength: 1
+                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
                     ip:
                       description: IP defines an IP endpoint. Supports both IPv4 and
                         IPv6 addresses.
@@ -22341,6 +22347,8 @@ spec:
                       Otherwise, if it is set to false or not set (defaulting to false),
                       the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.
                       This setting determines whether to prioritize accessibility over strict security in case of authorization service failure.
+
+                      If set to true, the External Authorization will also be bypassed if its configuration is invalid.
                     type: boolean
                   grpc:
                     description: |-