Repository: envoyproxy/gateway

Issue:
Add support for specifying alt_stat_name for an upstream cluster
*Description*:
Add support for specifying **alt_stat_name** for an upstream cluster in the Envoy configuration. This would be extremely useful for better identifying services in observability. 
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto

[optional *Relevant Links*:]
https://envoyproxy.slack.com/archives/C03E6NHLESV/p1731494818346729

Hints from issue comments:
@zirain: looks like [ClusterSettings](https://github.com/envoyproxy/gateway/blob/cc7104891d49d1c89b15f4b712ef055dbf4d65c9/api/v1alpha1/shared_types.go#L521) is a good place for this
@sekar-saravanan can you share more details about the user case@arkodg: can we auto populate this to a backendRef FQDN instead ?@sekar-saravanan: @zirain This is primarily for observability purposes. Currently, the envoy_cluster_name label provided by the EG metric appears as follows: _**httproute/seceng/gateway-dummy-service-external-origin/rule/0.**_ 
Supporting a configurable alt_stats_name would significantly improve the manageability and readability of metrics, making them more user-friendly.@github-actions: This issue has been automatically marked as stale because it has not had activity in the last 30 days.@guydc: If users control the prefix, they can decide to merge stats of various clusters when per-route-rule stat granularity is not required. This would also make it possible to better control scale of stats, which could be significant in EG, due to the way clusters are created. 

Auto-generating the alt_name (if user opts-in) would be a good option to reduce cardinality as well. I think that there are some questions, though:
- What should the alt_name be when a Backend with multiple FQDNs or no FQDNs is used? In this case, it might be better to use the resource's namespaced-name. 
- What should the alt_name be when multiple backends are referenced by a route rule? 
@guydc: Notes from community meeting with @arkodg, @zhaohuabing :
- User opt-in is required, as applying an alt_stat_name may lead to stats being merged across route rules and http routes, creating an incompatible change.  
- Auto-Generating an alt_stat_name based on namespaced-name of xRoute and BackendRef(s) reduces the scale of metrics and makes it easier to for users to search for metrics based on the service (as requested in this issue), instead of an anonymous indexed route rule. We may need to truncate the stat name if the list of backends is too long. 
- If we adopt weighted clusters, as mentioned in #5307, there would not be a need to collapse stats, as clusters would be created 1:1 with Backends/Services/ServiceImports. 

So, if a user attaches a BTP to a route and enables a new `statNameFromBackends` knob, given the following route:

```
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: http-app-1
spec:
  parentRefs:
  - name: my-gateway
  hostnames:
  - "foo.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /bar
    backendRefs:
    - name: my-service1
      port: 8080
    - name: my-service2
      port: 8080
```

The cluster alt_stat_name would look something like `default/http-app-1/default/my-service1/default/my-service2`. 

@sekar-saravanan - WDYT? 
@arkodg: I like how Istio solved this issue with a `inboundClusterStatName` setting in the top level global config https://istio.io/latest/docs/reference/config/istio.mesh.v1alpha1/

```
Name to be used while emitting statistics for inbound clusters. The same pattern is used while computing stat prefix for network filters like TCP and Redis. By default, Istio emits statistics with the pattern inbound|<port>|<port-name>|<service-FQDN>. For example inbound|7443|grpc-reviews|reviews.prod.svc.cluster.local. This can be used to override that pattern.

A Pattern can be composed of various pre-defined variables. The following variables are supported.

%SERVICE% - Will be substituted with short hostname of the service.
%SERVICE_NAME% - Will be substituted with name of the service.
%SERVICE_FQDN% - Will be substituted with FQDN of the service.
%SERVICE_PORT% - Will be substituted with port of the service.
%TARGET_PORT% - Will be substituted with the target port of the service.
%SERVICE_PORT_NAME% - Will be substituted with port name of the service.
Following are some examples of supported patterns for reviews:

%SERVICE_FQDN%_%SERVICE_PORT% will use reviews.prod.svc.cluster.local_7443 as the stats name.
%SERVICE% will use reviews.prod as the stats name.
```

Envoy Gateway can do something similar by 

1. exposing a `clusterStatsName` in EnvoyProxy under [telemetry.metrics](https://gateway.envoyproxy.io/docs/api/extension_types/#proxymetrics)
2. there can be another per route override available in BackendTrafficPolicy under `telemetry`
3. support a range of formatters from `ROUTE_KIND` , `ROUTE_NAME`, `ROUTE_RULE_NAME`, `ROUTE_RULE_NUMBER`, `BACKEND_REFS` `XDS_VHOST_DOMAIN`@guydc: > I like how Istio solved this issue with a inboundClusterStatName 

+1 to this approach@sekar-saravanan: > I like how Istio solved this issue with a inboundClusterStatName

+1 to this approach



Solution patch:
diff --git a/api/v1alpha1/backend_types.go b/api/v1alpha1/backend_types.go
index e5891d42e..ceec90834 100644
--- a/api/v1alpha1/backend_types.go
+++ b/api/v1alpha1/backend_types.go
@@ -153,7 +153,8 @@ type BackendSpec struct {
 	Fallback *bool `json:"fallback,omitempty"`
 
 	// TLS defines the TLS settings for the backend.
-	// Only supported for DynamicResolver backends.
+	// TLS.CACertificateRefs and TLS.WellKnownCACertificates can only be specified for DynamicResolver backends.
+	// TLS.InsecureSkipVerify can be specified for any Backends
 	//
 	// +optional
 	TLS *BackendTLSSettings `json:"tls,omitempty"`
@@ -161,7 +162,7 @@ type BackendSpec struct {
 
 // BackendTLSSettings holds the TLS settings for the backend.
 // +kubebuilder:validation:XValidation:message="must not contain both CACertificateRefs and WellKnownCACertificates",rule="!(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")"
-// +kubebuilder:validation:XValidation:message="must specify either CACertificateRefs or WellKnownCACertificates",rule="(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")"
+// +kubebuilder:validation:XValidation:message="must not contain either CACertificateRefs or WellKnownCACertificates when InsecureSkipVerify is enabled",rule="!((has(self.insecureSkipVerify) && self.insecureSkipVerify) && ((has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0) || (has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")))"
 type BackendTLSSettings struct {
 	// CACertificateRefs contains one or more references to Kubernetes objects that
 	// contain TLS certificates of the Certificate Authorities that can be used
@@ -197,7 +198,6 @@ type BackendTLSSettings struct {
 	//
 	// +kubebuilder:default=false
 	// +optional
-	// +notImplementedHide
 	InsecureSkipVerify *bool `json:"insecureSkipVerify,omitempty"`
 }
 
diff --git a/api/v1alpha1/envoyproxy_metric_types.go b/api/v1alpha1/envoyproxy_metric_types.go
index 69ce7bdfa..320b7436c 100644
--- a/api/v1alpha1/envoyproxy_metric_types.go
+++ b/api/v1alpha1/envoyproxy_metric_types.go
@@ -41,6 +41,22 @@ type ProxyMetrics struct {
 	//
 	// +optional
 	EnableRequestResponseSizesStats *bool `json:"enableRequestResponseSizesStats,omitempty"`
+
+	// ClusterStatName defines the value of cluster alt_stat_name, determining how cluster stats are named.
+	// For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html
+	// The supported operators for this pattern are:
+	// %ROUTE_NAME%: name of Gateway API xRoute resource
+	// %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+	// %ROUTE_KIND%: kind of Gateway API xRoute resource
+	// %ROUTE_RULE_NAME%: name of the Gateway API xRoute section
+	// %ROUTE_RULE_NUMBER%: name of the Gateway API xRoute section
+	// %BACKEND_REFS%: names of all backends referenced in <NAMESPACE>/<NAME>|<NAMESPACE>/<NAME>|... format
+	// Only xDS Clusters created for HTTPRoute and GRPCRoute are currently supported.
+	// Default: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/rule/%ROUTE_RULE_NUMBER%
+	// Example: httproute/my-ns/my-route/rule/0
+	//
+	// +optional
+	ClusterStatName *string `json:"clusterStatName,omitempty"`
 }
 
 // ProxyMetricSink defines the sink of metrics.
diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go
index 97ee9dea3..c81fe1c5d 100644
--- a/api/v1alpha1/envoyproxy_types.go
+++ b/api/v1alpha1/envoyproxy_types.go
@@ -266,6 +266,24 @@ const (
 
 	// EnvoyFilterBuffer defines the Envoy HTTP buffer filter
 	EnvoyFilterBuffer EnvoyFilter = "envoy.filters.http.buffer"
+
+	// StatFormatterRouteName defines the Route Name formatter for stats
+	StatFormatterRouteName string = "%ROUTE_NAME%"
+
+	// StatFormatterRouteNamespace defines the Route Name formatter for stats
+	StatFormatterRouteNamespace string = "%ROUTE_NAMESPACE%"
+
+	// StatFormatterRouteKind defines the Route Name formatter for stats
+	StatFormatterRouteKind string = "%ROUTE_KIND%"
+
+	// StatFormatterRouteRuleName defines the Route Name formatter for stats
+	StatFormatterRouteRuleName string = "%ROUTE_RULE_NAME%"
+
+	// StatFormatterRouteRuleNumber defines the Route Name formatter for stats
+	StatFormatterRouteRuleNumber string = "%ROUTE_RULE_NUMBER%"
+
+	// StatFormatterBackendRefs defines the Route Name formatter for stats
+	StatFormatterBackendRefs string = "%BACKEND_REFS%"
 )
 
 type ProxyTelemetry struct {
diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go
index 482d38b21..12226c304 100644
--- a/api/v1alpha1/validation/envoyproxy_validate.go
+++ b/api/v1alpha1/validation/envoyproxy_validate.go
@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"net"
 	"net/netip"
+	"regexp"
 
 	"github.com/dominikbraun/graph"
 	utilerrors "k8s.io/apimachinery/pkg/util/errors"
@@ -204,6 +205,12 @@ func validateProxyTelemetry(spec *egv1a1.EnvoyProxySpec) []error {
 				}
 			}
 		}
+
+		if spec.Telemetry.Metrics.ClusterStatName != nil {
+			if clusterStatErrs := validateClusterStatName(*spec.Telemetry.Metrics.ClusterStatName); clusterStatErrs != nil {
+				errs = append(errs, clusterStatErrs...)
+			}
+		}
 	}
 
 	return errs
@@ -283,3 +290,26 @@ func validateFilterOrder(filterOrder []egv1a1.FilterPosition) error {
 
 	return nil
 }
+
+func validateClusterStatName(clusterStatName string) []error {
+	supportedOperators := map[string]bool{
+		egv1a1.StatFormatterRouteName:       true,
+		egv1a1.StatFormatterRouteNamespace:  true,
+		egv1a1.StatFormatterRouteKind:       true,
+		egv1a1.StatFormatterRouteRuleName:   true,
+		egv1a1.StatFormatterRouteRuleNumber: true,
+		egv1a1.StatFormatterBackendRefs:     true,
+	}
+
+	var errs []error
+	re := regexp.MustCompile("%[^%]*%")
+	matches := re.FindAllString(clusterStatName, -1)
+	for _, operator := range matches {
+		if _, ok := supportedOperators[operator]; !ok {
+			err := fmt.Errorf("unable to configure Cluster Stat Name with unsupported operator: %s", operator)
+			errs = append(errs, err)
+		}
+	}
+
+	return errs
+}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index fd5f76573..0feeda228 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -5096,6 +5096,11 @@ func (in *ProxyMetrics) DeepCopyInto(out *ProxyMetrics) {
 		*out = new(bool)
 		**out = **in
 	}
+	if in.ClusterStatName != nil {
+		in, out := &in.ClusterStatName, &out.ClusterStatName
+		*out = new(string)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyMetrics.
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 eb4d4077b..3688b15c9 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
@@ -157,7 +157,8 @@ spec:
               tls:
                 description: |-
                   TLS defines the TLS settings for the backend.
-                  Only supported for DynamicResolver backends.
+                  TLS.CACertificateRefs and TLS.WellKnownCACertificates can only be specified for DynamicResolver backends.
+                  TLS.InsecureSkipVerify can be specified for any Backends
                 properties:
                   caCertificateRefs:
                     description: |-
@@ -235,10 +236,12 @@ spec:
                   rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs)
                     > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates
                     != "")'
-                - message: must specify either CACertificateRefs or WellKnownCACertificates
-                  rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs)
-                    > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates
-                    != "")
+                - message: must not contain either CACertificateRefs or WellKnownCACertificates
+                    when InsecureSkipVerify is enabled
+                  rule: '!((has(self.insecureSkipVerify) && self.insecureSkipVerify)
+                    && ((has(self.caCertificateRefs) && size(self.caCertificateRefs)
+                    > 0) || (has(self.wellKnownCACertificates) && self.wellKnownCACertificates
+                    != "")))'
               type:
                 default: Endpoints
                 description: Type defines the type of the backend. Defaults to "Endpoints"
diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
index 4122ba325..329cf2733 100644
--- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -12599,6 +12599,21 @@ spec:
                     description: Metrics defines metrics configuration for managed
                       proxies.
                     properties:
+                      clusterStatName:
+                        description: |-
+                          ClusterStatName defines the value of cluster alt_stat_name, determining how cluster stats are named.
+                          For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html
+                          The supported operators for this pattern are:
+                          %ROUTE_NAME%: name of Gateway API xRoute resource
+                          %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+                          %ROUTE_KIND%: kind of Gateway API xRoute resource
+                          %ROUTE_RULE_NAME%: name of the Gateway API xRoute section
+                          %ROUTE_RULE_NUMBER%: name of the Gateway API xRoute section
+                          %BACKEND_REFS%: names of all backends referenced in <NAMESPACE>/<NAME>|<NAMESPACE>/<NAME>|... format
+                          Only xDS Clusters created for HTTPRoute and GRPCRoute are currently supported.
+                          Default: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/rule/%ROUTE_RULE_NUMBER%
+                          Example: httproute/my-ns/my-route/rule/0
+                        type: string
                       enablePerEndpointStats:
                         description: |-
                           EnablePerEndpointStats enables per endpoint envoy stats metrics.
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 1b01448c6..a821ded07 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
@@ -156,7 +156,8 @@ spec:
               tls:
                 description: |-
                   TLS defines the TLS settings for the backend.
-                  Only supported for DynamicResolver backends.
+                  TLS.CACertificateRefs and TLS.WellKnownCACertificates can only be specified for DynamicResolver backends.
+                  TLS.InsecureSkipVerify can be specified for any Backends
                 properties:
                   caCertificateRefs:
                     description: |-
@@ -234,10 +235,12 @@ spec:
                   rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs)
                     > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates
                     != "")'
-                - message: must specify either CACertificateRefs or WellKnownCACertificates
-                  rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs)
-                    > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates
-                    != "")
+                - message: must not contain either CACertificateRefs or WellKnownCACertificates
+                    when InsecureSkipVerify is enabled
+                  rule: '!((has(self.insecureSkipVerify) && self.insecureSkipVerify)
+                    && ((has(self.caCertificateRefs) && size(self.caCertificateRefs)
+                    > 0) || (has(self.wellKnownCACertificates) && self.wellKnownCACertificates
+                    != "")))'
               type:
                 default: Endpoints
                 description: Type defines the type of the backend. Defaults to "Endpoints"
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
index 0c2dae98f..0a066f367 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -12598,6 +12598,21 @@ spec:
                     description: Metrics defines metrics configuration for managed
                       proxies.
                     properties:
+                      clusterStatName:
+                        description: |-
+                          ClusterStatName defines the value of cluster alt_stat_name, determining how cluster stats are named.
+                          For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html
+                          The supported operators for this pattern are:
+                          %ROUTE_NAME%: name of Gateway API xRoute resource
+                          %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+                          %ROUTE_KIND%: kind of Gateway API xRoute resource
+                          %ROUTE_RULE_NAME%: name of the Gateway API xRoute section
+                          %ROUTE_RULE_NUMBER%: name of the Gateway API xRoute section
+                          %BACKEND_REFS%: names of all backends referenced in <NAMESPACE>/<NAME>|<NAMESPACE>/<NAME>|... format
+                          Only xDS Clusters created for HTTPRoute and GRPCRoute are currently supported.
+                          Default: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/rule/%ROUTE_RULE_NUMBER%
+                          Example: httproute/my-ns/my-route/rule/0
+                        type: string
                       enablePerEndpointStats:
                         description: |-
                           EnablePerEndpointStats enables per endpoint envoy stats metrics.
diff --git a/internal/gatewayapi/backend.go b/internal/gatewayapi/backend.go
index 6aa614a05..59a3cf5d0 100644
--- a/internal/gatewayapi/backend.go
+++ b/internal/gatewayapi/backend.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 
 	"k8s.io/apimachinery/pkg/util/validation"
+	"k8s.io/utils/ptr"
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 	"github.com/envoyproxy/gateway/internal/gatewayapi/status"
@@ -48,20 +49,29 @@ func validateBackend(backend *egv1a1.Backend) status.Error {
 				status.RouteReasonInvalidBackendRef,
 			)
 		}
-	} else {
-		if backend.Spec.TLS != nil {
-			if backend.Spec.TLS.WellKnownCACertificates != nil {
-				return status.NewRouteStatusError(
-					fmt.Errorf("TLS.WellKnownCACertificates settings can only be specified for DynamicResolver backends"),
-					status.RouteReasonInvalidBackendRef,
-				)
-			}
-			if len(backend.Spec.TLS.CACertificateRefs) > 0 {
-				return status.NewRouteStatusError(
-					fmt.Errorf("TLS.CACertificateRefs settings can only be specified for DynamicResolver backends"),
-					status.RouteReasonInvalidBackendRef,
-				)
-			}
+
+		if backend.Spec.TLS != nil &&
+			!ptr.Deref(backend.Spec.TLS.InsecureSkipVerify, false) &&
+			backend.Spec.TLS.WellKnownCACertificates == nil &&
+			len(backend.Spec.TLS.CACertificateRefs) == 0 {
+			return status.NewRouteStatusError(
+				fmt.Errorf("must specify either CACertificateRefs or WellKnownCACertificates for DynamicResolver type when InsecureSkipVerify is unset or false"),
+				status.RouteReasonInvalidBackendRef,
+			)
+		}
+
+	} else if backend.Spec.TLS != nil {
+		if backend.Spec.TLS.WellKnownCACertificates != nil {
+			return status.NewRouteStatusError(
+				fmt.Errorf("TLS.WellKnownCACertificates settings can only be specified for DynamicResolver backends"),
+				status.RouteReasonInvalidBackendRef,
+			)
+		}
+		if len(backend.Spec.TLS.CACertificateRefs) > 0 {
+			return status.NewRouteStatusError(
+				fmt.Errorf("TLS.CACertificateRefs settings can only be specified for DynamicResolver backends"),
+				status.RouteReasonInvalidBackendRef,
+			)
 		}
 	}
 
diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go
index dc5c86b0f..d7e767e40 100644
--- a/internal/gatewayapi/backendtlspolicy.go
+++ b/internal/gatewayapi/backendtlspolicy.go
@@ -38,9 +38,15 @@ func (t *Translator) applyBackendTLSSetting(
 	// and not from the BackendTLSPolicy. This is because the BackendTLSPolicy requires a valid hostname, and
 	// dynamic resolvers's hostname is not fixed.
 	if isDynamicResolver {
-		if tlsBundle, err = t.processBackendTLSConfig(backendRef, backendNamespace, resources); err != nil {
+		upstreamConfig, err := t.processDynamicResolverBackendTLSConfig(backendRef, backendNamespace, resources)
+		if err != nil {
 			return nil, err
 		}
+
+		if tlsBundle, err = t.applyCommonBackendTLSConfig(upstreamConfig, backendRef, backendNamespace, resources); err != nil {
+			return nil, err
+		}
+
 		return t.applyEnvoyProxyBackendTLSSetting(tlsBundle, resources, envoyProxy)
 	}
 
@@ -49,43 +55,74 @@ func (t *Translator) applyBackendTLSSetting(
 		return nil, err
 	}
 
-	if tlsBundle, err = t.applyEnvoyProxyBackendTLSSetting(upstreamConfig, resources, envoyProxy); err != nil {
+	if tlsBundle, err = t.applyCommonBackendTLSConfig(upstreamConfig, backendRef, backendNamespace, resources); err != nil {
+		return nil, err
+	}
+
+	if tlsBundle, err = t.applyEnvoyProxyBackendTLSSetting(tlsBundle, resources, envoyProxy); err != nil {
 		return nil, err
 	}
 	return tlsBundle, nil
 }
 
-func (t *Translator) processBackendTLSConfig(
+func (t *Translator) applyCommonBackendTLSConfig(
+	tlsConfig *ir.TLSUpstreamConfig,
 	backendRef gwapiv1.BackendObjectReference,
 	backendNamespace string,
 	resources *resource.Resources,
 ) (*ir.TLSUpstreamConfig, error) {
+	if tlsConfig == nil || KindDerefOr(backendRef.Kind, resource.KindService) != resource.KindBackend {
+		return tlsConfig, nil
+	}
+
 	backend := resources.GetBackend(backendNamespace, string(backendRef.Name))
 	if backend == nil {
 		return nil, fmt.Errorf("backend %s not found", backendRef.Name)
 	}
 	if backend.Spec.TLS == nil {
+		return tlsConfig, nil
+	}
+
+	tlsConfig.InsecureSkipVerify = ptr.Deref(backend.Spec.TLS.InsecureSkipVerify, false)
+	return tlsConfig, nil
+}
+
+func (t *Translator) processDynamicResolverBackendTLSConfig(
+	backendRef gwapiv1.BackendObjectReference,
+	backendNamespace string,
+	resources *resource.Resources,
+) (*ir.TLSUpstreamConfig, error) {
+	backend := resources.GetBackend(backendNamespace, string(backendRef.Name))
+	if backend == nil {
+		return nil, fmt.Errorf("backend %s not found", backendRef.Name)
+	}
+	if backend.Spec.TLS == nil || (len(backend.Spec.TLS.CACertificateRefs) == 0 && backend.Spec.TLS.WellKnownCACertificates == nil) {
 		return nil, nil
 	}
 
 	tlsBundle := &ir.TLSUpstreamConfig{
-		UseSystemTrustStore: ptr.Deref(backend.Spec.TLS.WellKnownCACertificates, "") == gwapiv1a3.WellKnownCACertificatesSystem,
+		InsecureSkipVerify: ptr.Deref(backend.Spec.TLS.InsecureSkipVerify, false),
 	}
-	if tlsBundle.UseSystemTrustStore {
-		tlsBundle.CACertificate = &ir.TLSCACertificate{
-			Name: fmt.Sprintf("%s/%s-ca", backend.Name, backend.Namespace),
+
+	if !tlsBundle.InsecureSkipVerify {
+		tlsBundle.UseSystemTrustStore = ptr.Deref(backend.Spec.TLS.WellKnownCACertificates, "") == gwapiv1a3.WellKnownCACertificatesSystem
+
+		if tlsBundle.UseSystemTrustStore {
+			tlsBundle.CACertificate = &ir.TLSCACertificate{
+				Name: fmt.Sprintf("%s/%s-ca", backend.Name, backend.Namespace),
+			}
+		} else {
+			caCert, err := getCaCertsFromCARefs(backend.Spec.TLS.CACertificateRefs, resources)
+			if err != nil {
+				return nil, err
+			}
+			tlsBundle.CACertificate = &ir.TLSCACertificate{
+				Certificate: caCert,
+				Name:        fmt.Sprintf("%s/%s-ca", backend.Name, backend.Namespace),
+			}
 		}
-		return tlsBundle, nil
 	}
 
-	caCert, err := getCaCertsFromCARefs(backend.Spec.TLS.CACertificateRefs, resources)
-	if err != nil {
-		return nil, err
-	}
-	tlsBundle.CACertificate = &ir.TLSCACertificate{
-		Certificate: caCert,
-		Name:        fmt.Sprintf("%s/%s-ca", backend.Name, backend.Namespace),
-	}
 	return tlsBundle, nil
 }
 
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index 9c95e9d87..05edb5a00 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -187,6 +187,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
 		irRoutes []*ir.HTTPRoute
 		errs     = &status.MultiStatusError{}
 	)
+	pattern := getStatPattern(httpRoute, parentRef)
 
 	// process each HTTPRouteRule, generate a unique Xds IR HTTPRoute per match of the rule
 	for ruleIdx, rule := range httpRoute.Spec.Rules {
@@ -221,7 +222,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
 		allDs := []*ir.DestinationSetting{}
 		failedProcessDestination := false
 		hasDynamicResolver := false
-
+		backendRefNames := make([]string, len(rule.BackendRefs))
 		// process each backendRef, and calculate the destination settings for this rule
 		for i, backendRef := range rule.BackendRefs {
 			settingName := irDestinationSettingName(destName, i)
@@ -245,6 +246,8 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
 			if ds.IsDynamicResolver {
 				hasDynamicResolver = true
 			}
+			backendNamespace := NamespaceDerefOr(backendRef.Namespace, httpRoute.GetNamespace())
+			backendRefNames[i] = fmt.Sprintf("%s/%s", backendNamespace, backendRef.Name)
 		}
 
 		// process each ir route
@@ -280,6 +283,10 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
 				destination.Settings = allDs
 				irRoute.Destination = destination
 			}
+
+			if pattern != "" {
+				destination.StatName = ptr.To(buildStatName(pattern, httpRoute, rule.Name, ruleIdx, backendRefNames))
+			}
 		}
 
 		if hasDynamicResolver && len(rule.BackendRefs) > 1 {
@@ -627,6 +634,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 		irRoutes []*ir.HTTPRoute
 		errs     = &status.MultiStatusError{}
 	)
+	pattern := getStatPattern(grpcRoute, parentRef)
 
 	// compute matches, filters, backends
 	for ruleIdx, rule := range grpcRoute.Spec.Rules {
@@ -654,6 +662,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 		allDs := []*ir.DestinationSetting{}
 		failedProcessDestination := false
 
+		backendRefNames := make([]string, len(rule.BackendRefs))
 		for i, backendRef := range rule.BackendRefs {
 			settingName := irDestinationSettingName(destName, i)
 			ds, err := t.processDestination(settingName, backendRef, parentRef, grpcRoute, resources)
@@ -670,6 +679,8 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 				continue
 			}
 			allDs = append(allDs, ds)
+			backendNamespace := NamespaceDerefOr(backendRef.Namespace, grpcRoute.GetNamespace())
+			backendRefNames[i] = fmt.Sprintf("%s/%s", backendNamespace, backendRef.Name)
 		}
 
 		// process each ir route
@@ -700,6 +711,10 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 				destination.Settings = allDs
 				irRoute.Destination = destination
 			}
+
+			if pattern != "" {
+				destination.StatName = ptr.To(buildStatName(pattern, grpcRoute, rule.Name, ruleIdx, backendRefNames))
+			}
 		}
 
 		// TODO handle:
@@ -1973,3 +1988,31 @@ func backendAppProtocolToIRAppProtocol(ap egv1a1.AppProtocolType, defaultProtoco
 		return defaultProtocol
 	}
 }
+
+func getStatPattern(routeContext RouteContext, parentRef *RouteParentContext) string {
+	var pattern string
+	var envoyProxy *egv1a1.EnvoyProxy
+	gatewayCtx := GetRouteParentContext(routeContext, *parentRef.ParentReference).GetGateway()
+	if gatewayCtx != nil {
+		envoyProxy = gatewayCtx.envoyProxy
+	}
+	if envoyProxy != nil && envoyProxy.Spec.Telemetry != nil && envoyProxy.Spec.Telemetry.Metrics != nil &&
+		envoyProxy.Spec.Telemetry.Metrics.ClusterStatName != nil {
+		pattern = *envoyProxy.Spec.Telemetry.Metrics.ClusterStatName
+	}
+	return pattern
+}
+
+func buildStatName(pattern string, route RouteContext, ruleName *gwapiv1.SectionName, idx int, refs []string) string {
+	statName := strings.ReplaceAll(pattern, egv1a1.StatFormatterRouteName, route.GetName())
+	statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteNamespace, route.GetNamespace())
+	statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteKind, route.GetObjectKind().GroupVersionKind().Kind)
+	if ruleName == nil {
+		statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, "-")
+	} else {
+		statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, string(*ruleName))
+	}
+	statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleNumber, fmt.Sprintf("%d", idx))
+	statName = strings.ReplaceAll(statName, egv1a1.StatFormatterBackendRefs, strings.Join(refs, "|"))
+	return statName
+}
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index c2c3c39cc..3433f6a51 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -1497,6 +1497,7 @@ type RouteDestination struct {
 	// to check if this route destination already exists and can be
 	// reused
 	Name     string                `json:"name" yaml:"name"`
+	StatName *string               `json:"statName,omitempty" yaml:"statName,omitempty"`
 	Settings []*DestinationSetting `json:"settings,omitempty" yaml:"settings,omitempty"`
 	// Metadata is used to enrich envoy route metadata with user and provider-specific information
 	// RouteDestination metadata is primarily derived from the xRoute resources. In some cases,
@@ -2895,11 +2896,13 @@ type TLSUpstreamConfig struct {
 	CACertificate       *TLSCACertificate `json:"caCertificate,omitempty" yaml:"caCertificate,omitempty"`
 	TLSConfig           `json:",inline"`
 	SubjectAltNames     []SubjectAltName `json:"subjectAltNames,omitempty" yaml:"subjectAltNames,omitempty"`
+	InsecureSkipVerify  bool             `json:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty"`
 }
 
 func (t *TLSUpstreamConfig) ToTLSConfig() (*tls.Config, error) {
 	// nolint:gosec
 	tlsConfig := &tls.Config{}
+	tlsConfig.InsecureSkipVerify = t.InsecureSkipVerify
 	if t.SNI != nil {
 		tlsConfig.ServerName = *t.SNI
 	}
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index de924f1d5..344ed66ee 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -3065,6 +3065,11 @@ func (in *RoundRobin) DeepCopy() *RoundRobin {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *RouteDestination) DeepCopyInto(out *RouteDestination) {
 	*out = *in
+	if in.StatName != nil {
+		in, out := &in.StatName, &out.StatName
+		*out = new(string)
+		**out = **in
+	}
 	if in.Settings != nil {
 		in, out := &in.Settings, &out.Settings
 		*out = make([]*DestinationSetting, len(*in))
diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go
index b17e48379..8d811c2d6 100644
--- a/internal/xds/translator/cluster.go
+++ b/internal/xds/translator/cluster.go
@@ -69,6 +69,7 @@ type xdsClusterArgs struct {
 	useClientProtocol bool
 	ipFamily          *egv1a1.IPFamily
 	metadata          *ir.ResourceMetadata
+	statName          *string
 }
 
 type EndpointType int
@@ -148,6 +149,10 @@ func buildXdsCluster(args *xdsClusterArgs) (*buildClusterResult, error) {
 		Metadata:                      buildXdsMetadata(args.metadata),
 	}
 
+	if args.statName != nil {
+		cluster.AltStatName = *args.statName
+	}
+
 	// 50% is the Envoy default value for panic threshold. No need to explicitly set it in this case.
 	if args.healthCheck != nil && args.healthCheck.PanicThreshold != nil && *args.healthCheck.PanicThreshold != 50 {
 		cluster.CommonLbConfig.HealthyPanicThreshold = &xdstype.Percent{
@@ -1042,6 +1047,7 @@ type ExtraArgs struct {
 	http1Settings *ir.HTTP1Settings
 	http2Settings *ir.HTTP2Settings
 	ipFamily      *egv1a1.IPFamily
+	statName      *string
 }
 
 type clusterArgs interface {
@@ -1116,6 +1122,7 @@ func (httpRoute *HTTPRouteTranslator) asClusterArgs(name string,
 		useClientProtocol: ptr.Deref(httpRoute.UseClientProtocol, false),
 		ipFamily:          extra.ipFamily,
 		metadata:          metadata,
+		statName:          extra.statName,
 	}
 
 	// Populate traffic features.
diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go
index b89731fc1..f1f3ce137 100644
--- a/internal/xds/translator/translator.go
+++ b/internal/xds/translator/translator.go
@@ -523,6 +523,7 @@ func (t *Translator) addRouteToRouteConfig(
 				metrics:       metrics,
 				http1Settings: httpListener.HTTP1,
 				ipFamily:      determineIPFamily(httpRoute.Destination.Settings),
+				statName:      httpRoute.Destination.StatName,
 			}
 
 			if httpRoute.Traffic != nil && httpRoute.Traffic.HTTP2 != nil {
@@ -1046,7 +1047,7 @@ func buildXdsUpstreamTLSCASecret(tlsConfig *ir.TLSUpstreamConfig) *tlsv3.Secret
 	}
 }
 
-func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3.TransportSocket, error) {
+func buildValidationContext(tlsConfig *ir.TLSUpstreamConfig) *tlsv3.CommonTlsContext_CombinedValidationContext {
 	validationContext := &tlsv3.CommonTlsContext_CombinedCertificateValidationContext{
 		ValidationContextSdsSecretConfig: &tlsv3.SdsSecretConfig{
 			Name:      tlsConfig.CACertificate.Name,
@@ -1092,15 +1093,23 @@ func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3.
 		}
 	}
 
+	return &tlsv3.CommonTlsContext_CombinedValidationContext{
+		CombinedValidationContext: validationContext,
+	}
+}
+
+func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3.TransportSocket, error) {
 	tlsCtx := &tlsv3.UpstreamTlsContext{
 		CommonTlsContext: &tlsv3.CommonTlsContext{
 			TlsCertificateSdsSecretConfigs: nil,
-			ValidationContextType: &tlsv3.CommonTlsContext_CombinedValidationContext{
-				CombinedValidationContext: validationContext,
-			},
+			ValidationContextType:          nil,
 		},
 	}
 
+	if !tlsConfig.InsecureSkipVerify {
+		tlsCtx.CommonTlsContext.ValidationContextType = buildValidationContext(tlsConfig)
+	}
+
 	if tlsConfig.SNI != nil {
 		tlsCtx.Sni = *tlsConfig.SNI
 	}
diff --git a/release-notes/current.yaml b/release-notes/current.yaml
index 62338fa9e..ba3dcf22c 100644
--- a/release-notes/current.yaml
+++ b/release-notes/current.yaml
@@ -18,6 +18,7 @@ new features: |
   Added support for configuring hostname in active HTTP healthchecks.
   Added support for GatewayInfrastructure in gateway namespace mode.
   Added support for using extension server policies to in PostTranslateModify hook.
+  Added support for configuring cluster stat name for HTTPRoute and GRPCRoute in EnvoyProxy CRD.
 
 bug fixes: |
   Handle integer zone annotation values
diff --git a/site/content/en/v1.4/tasks/observability/gateway-api-metrics.md b/site/content/en/v1.4/tasks/observability/gateway-api-metrics.md
index d2583f3e6..08f8bc875 100644
--- a/site/content/en/v1.4/tasks/observability/gateway-api-metrics.md
+++ b/site/content/en/v1.4/tasks/observability/gateway-api-metrics.md
@@ -124,4 +124,4 @@ done
 
 ## Next Steps
 
-Check out the [Gateway Exported Metrics](./grafana-integration.md) section to learn more about the metrics exported by the Envoy Gateway.
+Check out the [Gateway Exported Metrics](./gateway-exported-metrics.md) section to learn more about the metrics exported by the Envoy Gateway.



Test patch:
diff --git a/api/v1alpha1/validation/envoyproxy_validate_test.go b/api/v1alpha1/validation/envoyproxy_validate_test.go
index f6ff1c6b2..0834bbe1a 100644
--- a/api/v1alpha1/validation/envoyproxy_validate_test.go
+++ b/api/v1alpha1/validation/envoyproxy_validate_test.go
@@ -6,6 +6,7 @@
 package validation
 
 import (
+	"fmt"
 	"reflect"
 	"testing"
 
@@ -759,6 +760,42 @@ func TestValidateEnvoyProxy(t *testing.T) {
 			},
 			expected: false,
 		},
+		{
+			name: "valid operators in ClusterStatName",
+			proxy: &egv1a1.EnvoyProxy{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				},
+				Spec: egv1a1.EnvoyProxySpec{
+					Telemetry: &egv1a1.ProxyTelemetry{
+						Metrics: &egv1a1.ProxyMetrics{
+							ClusterStatName: ptr.To(fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s", egv1a1.StatFormatterRouteName,
+								egv1a1.StatFormatterRouteName, egv1a1.StatFormatterRouteNamespace, egv1a1.StatFormatterRouteKind,
+								egv1a1.StatFormatterRouteRuleName, egv1a1.StatFormatterRouteRuleNumber, egv1a1.StatFormatterBackendRefs)),
+						},
+					},
+				},
+			},
+			expected: true,
+		},
+		{
+			name: "invalid operators in ClusterStatName",
+			proxy: &egv1a1.EnvoyProxy{
+				ObjectMeta: metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				},
+				Spec: egv1a1.EnvoyProxySpec{
+					Telemetry: &egv1a1.ProxyTelemetry{
+						Metrics: &egv1a1.ProxyMetrics{
+							ClusterStatName: ptr.To("%ROUTE_NAME%.%FOO%.%BAR%/my/%BACKEND_REFS%/%FOOBAR%"),
+						},
+					},
+				},
+			},
+			expected: false,
+		},
 	}
 
 	for i := range testCases {
diff --git a/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.in.yaml b/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.in.yaml
index ebef4f085..7cdcbef91 100644
--- a/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.in.yaml
+++ b/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.in.yaml
@@ -28,3 +28,12 @@ backends:
             address: 2.2.2.2
             port: 3001
           zone: zone2
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: Backend
+    metadata:
+      name: backend-2
+      namespace: default
+    spec:
+      type: DynamicResolver
+      tls:
+        insecureSkipVerify: false
diff --git a/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.out.yaml b/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.out.yaml
index 48cc40379..2f455877a 100644
--- a/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.out.yaml
+++ b/internal/gatewayapi/testdata/backend-invalid-tls-settings-with-endpoints.out.yaml
@@ -46,5 +46,24 @@ backends:
       reason: Accepted
       status: "False"
       type: Invalid
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: Backend
+  metadata:
+    creationTimestamp: null
+    name: backend-2
+    namespace: default
+  spec:
+    tls:
+      insecureSkipVerify: false
+    type: DynamicResolver
+  status:
+    conditions:
+    - lastTransitionTime: null
+      message: 'The Backend was not accepted: must specify either CACertificateRefs
+        or WellKnownCACertificates for DynamicResolver type when InsecureSkipVerify
+        is unset or false'
+      reason: Accepted
+      status: "False"
+      type: Invalid
 infraIR: {}
 xdsIR: {}
diff --git a/internal/gatewayapi/testdata/backend-with-skip-tls-verify.in.yaml b/internal/gatewayapi/testdata/backend-with-skip-tls-verify.in.yaml
new file mode 100644
index 000000000..6364d5c63
--- /dev/null
+++ b/internal/gatewayapi/testdata/backend-with-skip-tls-verify.in.yaml
@@ -0,0 +1,99 @@
+gateways:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: Gateway
+    metadata:
+      name: gateway-btls
+      namespace: envoy-gateway
+    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:
+      name: httproute-btls
+      namespace: envoy-gateway
+    spec:
+      parentRefs:
+        - namespace: envoy-gateway
+          name: gateway-btls
+          sectionName: http
+      rules:
+        - matches:
+            - path:
+                type: Exact
+                value: "/exact"
+          backendRefs:
+            - kind: Backend
+              group: gateway.envoyproxy.io
+              name: backend-1
+              namespace: backends
+              port: 8080
+
+referenceGrants:
+  - apiVersion: gateway.networking.k8s.io/v1alpha2
+    kind: ReferenceGrant
+    metadata:
+      name: refg-route-svc
+      namespace: backends
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: HTTPRoute
+          namespace: envoy-gateway
+        - group: gateway.networking.k8s.io
+          kind: Gateway
+          namespace: envoy-gateway
+        - group: gateway.networking.k8s.io
+          kind: BackendTLSPolicy
+          namespace: policies
+      to:
+        - group: gateway.envoyproxy.io
+          kind: Backend
+
+backends:
+  - apiVersion: gateway.envoyproxy.io/v1alpha1
+    kind: Backend
+    metadata:
+      name: backend-1
+      namespace: backends
+    spec:
+      endpoints:
+        - ip:
+            address: 1.1.1.1
+            port: 3001
+      tls:
+        insecureSkipVerify: true
+
+secrets:
+  - apiVersion: v1
+    kind: Secret
+    metadata:
+      name: ca-secret
+      namespace: policies
+    data:
+      ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+
+backendTLSPolicies:
+  - apiVersion: gateway.networking.k8s.io/v1alpha2
+    kind: BackendTLSPolicy
+    metadata:
+      name: policy-btls
+      namespace: backends
+    spec:
+      targetRefs:
+        - kind: Backend
+          group: gateway.envoyproxy.io
+          name: backend-1
+      validation:
+        caCertificateRefs:
+          - name: ca-secret
+            group: ""
+            kind: Secret
+        hostname: example.com
diff --git a/internal/gatewayapi/testdata/backend-with-skip-tls-verify.out.yaml b/internal/gatewayapi/testdata/backend-with-skip-tls-verify.out.yaml
new file mode 100644
index 000000000..02f7f78e1
--- /dev/null
+++ b/internal/gatewayapi/testdata/backend-with-skip-tls-verify.out.yaml
@@ -0,0 +1,213 @@
+backendTLSPolicies:
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+  kind: BackendTLSPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-btls
+    namespace: backends
+  spec:
+    targetRefs:
+    - group: gateway.envoyproxy.io
+      kind: Backend
+      name: backend-1
+    validation:
+      caCertificateRefs:
+      - group: ""
+        kind: Secret
+        name: ca-secret
+      hostname: example.com
+  status:
+    ancestors:
+    - ancestorRef:
+        name: gateway-btls
+        namespace: envoy-gateway
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+backends:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: Backend
+  metadata:
+    creationTimestamp: null
+    name: backend-1
+    namespace: backends
+  spec:
+    endpoints:
+    - ip:
+        address: 1.1.1.1
+        port: 3001
+    tls:
+      insecureSkipVerify: true
+  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-btls
+    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-btls
+    namespace: envoy-gateway
+  spec:
+    parentRefs:
+    - name: gateway-btls
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - group: gateway.envoyproxy.io
+        kind: Backend
+        name: backend-1
+        namespace: backends
+        port: 8080
+      matches:
+      - path:
+          type: Exact
+          value: /exact
+  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-btls
+        namespace: envoy-gateway
+        sectionName: http
+infraIR:
+  envoy-gateway/gateway-btls:
+    proxy:
+      listeners:
+      - address: null
+        name: envoy-gateway/gateway-btls/http
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-btls
+          gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+      name: envoy-gateway/gateway-btls
+      namespace: envoy-gateway-system
+xdsIR:
+  envoy-gateway/gateway-btls:
+    accessLog:
+      json:
+      - path: /dev/stdout
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-btls
+        namespace: envoy-gateway
+        sectionName: http
+      name: envoy-gateway/gateway-btls/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          metadata:
+            kind: HTTPRoute
+            name: httproute-btls
+            namespace: envoy-gateway
+          name: httproute/envoy-gateway/httproute-btls/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 1.1.1.1
+              port: 3001
+            metadata:
+              kind: Backend
+              name: backend-1
+              namespace: backends
+            name: httproute/envoy-gateway/httproute-btls/rule/0/backend/0
+            protocol: HTTP
+            tls:
+              alpnProtocols: null
+              caCertificate:
+                certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+                name: policy-btls/backends-ca
+              insecureSkipVerify: true
+              sni: example.com
+            weight: 1
+        hostname: '*'
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-btls
+          namespace: envoy-gateway
+        name: httproute/envoy-gateway/httproute-btls/rule/0/match/0/*
+        pathMatch:
+          distinct: false
+          exact: /exact
+          name: ""
+    readyListener:
+      address: 0.0.0.0
+      ipFamily: IPv4
+      path: /ready
+      port: 19003
diff --git a/internal/gatewayapi/testdata/envoyproxy-with-statname.in.yaml b/internal/gatewayapi/testdata/envoyproxy-with-statname.in.yaml
new file mode 100644
index 000000000..54dfc32ab
--- /dev/null
+++ b/internal/gatewayapi/testdata/envoyproxy-with-statname.in.yaml
@@ -0,0 +1,78 @@
+envoyProxyForGatewayClass:
+  apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: EnvoyProxy
+  metadata:
+    namespace: envoy-gateway-system
+    name: test
+  spec:
+    telemetry:
+      metrics:
+        clusterStatName: "%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_RULE_NAME%/%ROUTE_RULE_NUMBER%/%BACKEND_REFS%"
+    provider:
+      type: Kubernetes
+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
+grpcRoutes:
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+  kind: GRPCRoute
+  metadata:
+    namespace: default
+    name: grpcroute-1
+  spec:
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      - name: service-2
+        port: 8080
+      - name: service-3
+        port: 8080
+      - name: service-4
+        port: 8080
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-1
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/foo"
+      name: "foo"
+      backendRefs:
+      - name: service-3
+        port: 8080
+      - name: service-4
+        port: 8080
+    - matches:
+      - path:
+          value: "/"
+      name: "fallback"
+      backendRefs:
+      - name: service-1
+        port: 8080
diff --git a/internal/gatewayapi/testdata/envoyproxy-with-statname.out.yaml b/internal/gatewayapi/testdata/envoyproxy-with-statname.out.yaml
new file mode 100644
index 000000000..07d92ece8
--- /dev/null
+++ b/internal/gatewayapi/testdata/envoyproxy-with-statname.out.yaml
@@ -0,0 +1,326 @@
+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: 2
+      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
+grpcRoutes:
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+  kind: GRPCRoute
+  metadata:
+    creationTimestamp: null
+    name: grpcroute-1
+    namespace: default
+  spec:
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      - name: service-2
+        port: 8080
+      - name: service-3
+        port: 8080
+      - name: service-4
+        port: 8080
+  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
+        sectionName: http
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-1
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-3
+        port: 8080
+      - name: service-4
+        port: 8080
+      matches:
+      - path:
+          value: /foo
+      name: foo
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /
+      name: fallback
+  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
+        sectionName: http
+infraIR:
+  envoy-gateway/gateway-1:
+    proxy:
+      config:
+        apiVersion: gateway.envoyproxy.io/v1alpha1
+        kind: EnvoyProxy
+        metadata:
+          creationTimestamp: null
+          name: test
+          namespace: envoy-gateway-system
+        spec:
+          logging: {}
+          provider:
+            type: Kubernetes
+          telemetry:
+            metrics:
+              clusterStatName: '%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_RULE_NAME%/%ROUTE_RULE_NUMBER%/%BACKEND_REFS%'
+        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
+      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: true
+      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
+            sectionName: foo
+          name: httproute/default/httproute-1/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-3
+              namespace: default
+              sectionName: "8080"
+            name: httproute/default/httproute-1/rule/0/backend/0
+            protocol: HTTP
+            weight: 1
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-4
+              namespace: default
+              sectionName: "8080"
+            name: httproute/default/httproute-1/rule/0/backend/1
+            protocol: HTTP
+            weight: 1
+          statName: HTTPRoute/default/httproute-1/foo/0/default/service-3|default/service-4
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-1
+          namespace: default
+          sectionName: foo
+        name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /foo
+      - destination:
+          metadata:
+            kind: HTTPRoute
+            name: httproute-1
+            namespace: default
+            sectionName: fallback
+          name: httproute/default/httproute-1/rule/1
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-1
+              namespace: default
+              sectionName: "8080"
+            name: httproute/default/httproute-1/rule/1/backend/0
+            protocol: HTTP
+            weight: 1
+          statName: HTTPRoute/default/httproute-1/fallback/1/default/service-1
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-1
+          namespace: default
+          sectionName: fallback
+        name: httproute/default/httproute-1/rule/1/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /
+      - destination:
+          metadata:
+            kind: GRPCRoute
+            name: grpcroute-1
+            namespace: default
+          name: grpcroute/default/grpcroute-1/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-1
+              namespace: default
+              sectionName: "8080"
+            name: grpcroute/default/grpcroute-1/rule/0/backend/0
+            protocol: GRPC
+            weight: 1
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-2
+              namespace: default
+              sectionName: "8080"
+            name: grpcroute/default/grpcroute-1/rule/0/backend/1
+            protocol: GRPC
+            weight: 1
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-3
+              namespace: default
+              sectionName: "8080"
+            name: grpcroute/default/grpcroute-1/rule/0/backend/2
+            protocol: GRPC
+            weight: 1
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            metadata:
+              name: service-4
+              namespace: default
+              sectionName: "8080"
+            name: grpcroute/default/grpcroute-1/rule/0/backend/3
+            protocol: GRPC
+            weight: 1
+          statName: GRPCRoute/default/grpcroute-1/-/0/default/service-1|default/service-2|default/service-3|default/service-4
+        hostname: '*'
+        isHTTP2: true
+        metadata:
+          kind: GRPCRoute
+          name: grpcroute-1
+          namespace: default
+        name: grpcroute/default/grpcroute-1/rule/0/match/-1/*
+    metrics:
+      enablePerEndpointStats: false
+      enableRequestResponseSizesStats: false
+      enableVirtualHostStats: false
+    readyListener:
+      address: 0.0.0.0
+      ipFamily: IPv4
+      path: /ready
+      port: 19003
diff --git a/internal/xds/translator/testdata/in/xds-ir/backend-tls-skip-verify.yaml b/internal/xds/translator/testdata/in/xds-ir/backend-tls-skip-verify.yaml
new file mode 100644
index 000000000..fc74c38f3
--- /dev/null
+++ b/internal/xds/translator/testdata/in/xds-ir/backend-tls-skip-verify.yaml
@@ -0,0 +1,25 @@
+http:
+  - name: "first-listener"
+    address: "::"
+    port: 10080
+    hostnames:
+      - "*"
+    path:
+      mergeSlashes: true
+      escapedSlashesAction: UnescapeAndRedirect
+    routes:
+      - name: "first-route"
+        hostname: "*"
+        destination:
+          name: "first-route-dest"
+          settings:
+            - endpoints:
+                - host: "1.2.3.4"
+                  port: 50000
+              name: "first-route-dest/backend/0"
+              tls:
+                insecureSkipVerify: true
+                useSystemTrustStore: true
+                CACertificate:
+                  name: policy-btls/default-ca
+                sni: example.com
diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-stat-name.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-stat-name.yaml
new file mode 100644
index 000000000..d09a10b3c
--- /dev/null
+++ b/internal/xds/translator/testdata/in/xds-ir/http-route-stat-name.yaml
@@ -0,0 +1,36 @@
+http:
+- name: "first-listener"
+  address: "::"
+  port: 10080
+  hostnames:
+  - "*"
+  path:
+    mergeSlashes: true
+    escapedSlashesAction: UnescapeAndRedirect
+  routes:
+  - name: "first-route"
+    hostname: "*"
+    destination:
+      statName: "custom-stat-name"
+      name: "first-route-dest"
+      settings:
+      - endpoints:
+        - host: "1.1.1.1"
+          port: 50001
+        weight: 20
+        name: "first-route-dest/backend/0"
+      - endpoints:
+        - host: "2.2.2.2"
+          port: 50002
+        weight: 40
+        name: "first-route-dest/backend/1"
+      - endpoints:
+        - host: "3.3.3.3"
+          port: 50003
+        weight: 20
+        name: "first-route-dest/backend/2"
+      - endpoints:
+        - host: "4.4.4.4"
+          port: 50004
+        weight: 20
+        name: "first-route-dest/backend/3"
diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.clusters.yaml
new file mode 100644
index 000000000..8122060bc
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.clusters.yaml
@@ -0,0 +1,27 @@
+- circuitBreakers:
+    thresholds:
+    - maxRetries: 1024
+  commonLbConfig:
+    localityWeightedLbConfig: {}
+  connectTimeout: 10s
+  dnsLookupFamily: V4_PREFERRED
+  edsClusterConfig:
+    edsConfig:
+      ads: {}
+      resourceApiVersion: V3
+    serviceName: first-route-dest
+  ignoreHealthOnHostRemoval: true
+  lbPolicy: LEAST_REQUEST
+  name: first-route-dest
+  perConnectionBufferLimitBytes: 32768
+  transportSocketMatches:
+  - match:
+      name: first-route-dest/tls/0
+    name: first-route-dest/tls/0
+    transportSocket:
+      name: envoy.transport_sockets.tls
+      typedConfig:
+        '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
+        commonTlsContext: {}
+        sni: example.com
+  type: EDS
diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.endpoints.yaml
new file mode 100644
index 000000000..4257c2b40
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.endpoints.yaml
@@ -0,0 +1,16 @@
+- clusterName: first-route-dest
+  endpoints:
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 1.2.3.4
+            portValue: 50000
+      loadBalancingWeight: 1
+      metadata:
+        filterMetadata:
+          envoy.transport_socket_match:
+            name: first-route-dest/tls/0
+    loadBalancingWeight: 1
+    locality:
+      region: first-route-dest/backend/0
diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.listeners.yaml
new file mode 100644
index 000000000..80ae84fd1
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.listeners.yaml
@@ -0,0 +1,34 @@
+- address:
+    socketAddress:
+      address: '::'
+      portValue: 10080
+  defaultFilterChain:
+    filters:
+    - name: envoy.filters.network.http_connection_manager
+      typedConfig:
+        '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+        commonHttpProtocolOptions:
+          headersWithUnderscoresAction: REJECT_REQUEST
+        http2ProtocolOptions:
+          initialConnectionWindowSize: 1048576
+          initialStreamWindowSize: 65536
+          maxConcurrentStreams: 100
+        httpFilters:
+        - name: envoy.filters.http.router
+          typedConfig:
+            '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+            suppressEnvoyHeaders: true
+        mergeSlashes: true
+        normalizePath: true
+        pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT
+        rds:
+          configSource:
+            ads: {}
+            resourceApiVersion: V3
+          routeConfigName: first-listener
+        serverHeaderTransformation: PASS_THROUGH
+        statPrefix: http-10080
+        useRemoteAddress: true
+    name: first-listener
+  name: first-listener
+  perConnectionBufferLimitBytes: 32768
diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.routes.yaml
new file mode 100644
index 000000000..0b5b4bee7
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.routes.yaml
@@ -0,0 +1,14 @@
+- ignorePortInHostMatching: true
+  name: first-listener
+  virtualHosts:
+  - domains:
+    - '*'
+    name: first-listener/*
+    routes:
+    - match:
+        prefix: /
+      name: first-route
+      route:
+        cluster: first-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.secrets.yaml
new file mode 100644
index 000000000..1f76e2cec
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/backend-tls-skip-verify.secrets.yaml
@@ -0,0 +1,4 @@
+- name: policy-btls/default-ca
+  validationContext:
+    trustedCa:
+      filename: /etc/ssl/certs/ca-certificates.crt
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.clusters.yaml
new file mode 100644
index 000000000..6d9c237e1
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.clusters.yaml
@@ -0,0 +1,18 @@
+- altStatName: custom-stat-name
+  circuitBreakers:
+    thresholds:
+    - maxRetries: 1024
+  commonLbConfig:
+    localityWeightedLbConfig: {}
+  connectTimeout: 10s
+  dnsLookupFamily: V4_PREFERRED
+  edsClusterConfig:
+    edsConfig:
+      ads: {}
+      resourceApiVersion: V3
+    serviceName: first-route-dest
+  ignoreHealthOnHostRemoval: true
+  lbPolicy: LEAST_REQUEST
+  name: first-route-dest
+  perConnectionBufferLimitBytes: 32768
+  type: EDS
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.endpoints.yaml
new file mode 100644
index 000000000..f5633bd15
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.endpoints.yaml
@@ -0,0 +1,42 @@
+- clusterName: first-route-dest
+  endpoints:
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 1.1.1.1
+            portValue: 50001
+      loadBalancingWeight: 1
+    loadBalancingWeight: 20
+    locality:
+      region: first-route-dest/backend/0
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 2.2.2.2
+            portValue: 50002
+      loadBalancingWeight: 1
+    loadBalancingWeight: 40
+    locality:
+      region: first-route-dest/backend/1
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 3.3.3.3
+            portValue: 50003
+      loadBalancingWeight: 1
+    loadBalancingWeight: 20
+    locality:
+      region: first-route-dest/backend/2
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 4.4.4.4
+            portValue: 50004
+      loadBalancingWeight: 1
+    loadBalancingWeight: 20
+    locality:
+      region: first-route-dest/backend/3
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.listeners.yaml
new file mode 100644
index 000000000..80ae84fd1
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.listeners.yaml
@@ -0,0 +1,34 @@
+- address:
+    socketAddress:
+      address: '::'
+      portValue: 10080
+  defaultFilterChain:
+    filters:
+    - name: envoy.filters.network.http_connection_manager
+      typedConfig:
+        '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+        commonHttpProtocolOptions:
+          headersWithUnderscoresAction: REJECT_REQUEST
+        http2ProtocolOptions:
+          initialConnectionWindowSize: 1048576
+          initialStreamWindowSize: 65536
+          maxConcurrentStreams: 100
+        httpFilters:
+        - name: envoy.filters.http.router
+          typedConfig:
+            '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+            suppressEnvoyHeaders: true
+        mergeSlashes: true
+        normalizePath: true
+        pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT
+        rds:
+          configSource:
+            ads: {}
+            resourceApiVersion: V3
+          routeConfigName: first-listener
+        serverHeaderTransformation: PASS_THROUGH
+        statPrefix: http-10080
+        useRemoteAddress: true
+    name: first-listener
+  name: first-listener
+  perConnectionBufferLimitBytes: 32768
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.routes.yaml
new file mode 100644
index 000000000..0b5b4bee7
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-stat-name.routes.yaml
@@ -0,0 +1,14 @@
+- ignorePortInHostMatching: true
+  name: first-listener
+  virtualHosts:
+  - domains:
+    - '*'
+    name: first-listener/*
+    routes:
+    - match:
+        prefix: /
+      name: first-route
+      route:
+        cluster: first-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 53b146792..761d0ecc3 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -406,7 +406,7 @@ _Appears in:_
 | `endpoints` | _[BackendEndpoint](#backendendpoint) array_ |  true  |  | Endpoints defines the endpoints to be used when connecting to the backend. |
 | `appProtocols` | _[AppProtocolType](#appprotocoltype) array_ |  false  |  | AppProtocols defines the application protocols to be supported when connecting to the backend. |
 | `fallback` | _boolean_ |  false  |  | Fallback indicates whether the backend is designated as a fallback.<br />It is highly recommended to configure active or passive health checks to ensure that failover can be detected<br />when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.<br />The overprovisioning factor is set to 1.4, meaning the fallback backends will only start receiving traffic when<br />the health of the active backends falls below 72%. |
-| `tls` | _[BackendTLSSettings](#backendtlssettings)_ |  false  |  | TLS defines the TLS settings for the backend.<br />Only supported for DynamicResolver backends. |
+| `tls` | _[BackendTLSSettings](#backendtlssettings)_ |  false  |  | TLS defines the TLS settings for the backend.<br />TLS.CACertificateRefs and TLS.WellKnownCACertificates can only be specified for DynamicResolver backends.<br />TLS.InsecureSkipVerify can be specified for any Backends |
 
 
 #### BackendStatus
@@ -456,6 +456,7 @@ _Appears in:_
 | ---   | ---  | ---      | ---     | ---         |
 | `caCertificateRefs` | _LocalObjectReference array_ |  false  |  | CACertificateRefs contains one or more references to Kubernetes objects that<br />contain TLS certificates of the Certificate Authorities that can be used<br />as a trust anchor to validate the certificates presented by the backend.<br />A single reference to a Kubernetes ConfigMap or a Kubernetes Secret,<br />with the CA certificate in a key named `ca.crt` is currently supported.<br />If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be<br />specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified,<br />not both.<br />Only used for DynamicResolver backends. |
 | `wellKnownCACertificates` | _[WellKnownCACertificatesType](#wellknowncacertificatestype)_ |  false  |  | WellKnownCACertificates specifies whether system CA certificates may be used in<br />the TLS handshake between the gateway and backend pod.<br />If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs<br />must be specified with at least one entry for a valid configuration. Only one of<br />CACertificateRefs or WellKnownCACertificates may be specified, not both.<br />Only used for DynamicResolver backends. |
+| `insecureSkipVerify` | _boolean_ |  false  | false | InsecureSkipVerify indicates whether the upstream's certificate verification<br />should be skipped. Defaults to "false". |
 
 
 #### BackendTelemetry
@@ -3660,6 +3661,7 @@ _Appears in:_
 | `enableVirtualHostStats` | _boolean_ |  false  |  | EnableVirtualHostStats enables envoy stat metrics for virtual hosts. |
 | `enablePerEndpointStats` | _boolean_ |  false  |  | EnablePerEndpointStats enables per endpoint envoy stats metrics.<br />Please use with caution. |
 | `enableRequestResponseSizesStats` | _boolean_ |  false  |  | EnableRequestResponseSizesStats enables publishing of histograms tracking header and body sizes of requests and responses. |
+| `clusterStatName` | _string_ |  false  |  | ClusterStatName defines the value of cluster alt_stat_name, determining how cluster stats are named.<br />For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html<br />The supported operators for this pattern are:<br />%ROUTE_NAME%: name of Gateway API xRoute resource<br />%ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource<br />%ROUTE_KIND%: kind of Gateway API xRoute resource<br />%ROUTE_RULE_NAME%: name of the Gateway API xRoute section<br />%ROUTE_RULE_NUMBER%: name of the Gateway API xRoute section<br />%BACKEND_REFS%: names of all backends referenced in <NAMESPACE>/<NAME>\|<NAMESPACE>/<NAME>\|... format<br />Only xDS Clusters created for HTTPRoute and GRPCRoute are currently supported.<br />Default: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/rule/%ROUTE_RULE_NUMBER%<br />Example: httproute/my-ns/my-route/rule/0 |
 
 
 #### ProxyOpenTelemetrySink
diff --git a/site/content/en/latest/tasks/observability/gateway-api-metrics.md b/site/content/en/latest/tasks/observability/gateway-api-metrics.md
index d2583f3e6..08f8bc875 100644
--- a/site/content/en/latest/tasks/observability/gateway-api-metrics.md
+++ b/site/content/en/latest/tasks/observability/gateway-api-metrics.md
@@ -124,4 +124,4 @@ done
 
 ## Next Steps
 
-Check out the [Gateway Exported Metrics](./grafana-integration.md) section to learn more about the metrics exported by the Envoy Gateway.
+Check out the [Gateway Exported Metrics](./gateway-exported-metrics.md) section to learn more about the metrics exported by the Envoy Gateway.
diff --git a/test/cel-validation/backend_test.go b/test/cel-validation/backend_test.go
index 698b1533a..3ff5dca52 100644
--- a/test/cel-validation/backend_test.go
+++ b/test/cel-validation/backend_test.go
@@ -16,6 +16,7 @@ import (
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/ptr"
+	gwapiv1a3 "sigs.k8s.io/gateway-api/apis/v1alpha3"
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 )
@@ -300,6 +301,19 @@ func TestBackend(t *testing.T) {
 			},
 			wantErrors: []string{`spec.endpoints[0].unix.path: Invalid value: "string": unix domain socket path must not exceed 108 characters`},
 		},
+		{
+			desc: "dynamic resolver invalid WellKnownCACertificates and InsecureSkipVerify specified",
+			mutate: func(backend *egv1a1.Backend) {
+				backend.Spec = egv1a1.BackendSpec{
+					Type: ptr.To(egv1a1.BackendTypeDynamicResolver),
+					TLS: &egv1a1.BackendTLSSettings{
+						InsecureSkipVerify:      ptr.To(true),
+						WellKnownCACertificates: ptr.To(gwapiv1a3.WellKnownCACertificatesSystem),
+					},
+				}
+			},
+			wantErrors: []string{`must not contain either CACertificateRefs or WellKnownCACertificates when InsecureSkipVerify is enabled`},
+		},
 	}
 
 	for _, tc := range cases {
diff --git a/test/e2e/testdata/backend-tls.yaml b/test/e2e/testdata/backend-tls.yaml
index 3ff72eefd..b65767055 100644
--- a/test/e2e/testdata/backend-tls.yaml
+++ b/test/e2e/testdata/backend-tls.yaml
@@ -107,3 +107,48 @@ spec:
     - fqdn:
         hostname: gateway.envoyproxy.io
         port: 443
+---
+apiVersion: gateway.networking.k8s.io/v1alpha3
+kind: BackendTLSPolicy
+metadata:
+  name: policy-btls-ca-mismatch
+  namespace: gateway-conformance-infra
+spec:
+  targetRefs:
+    - group: gateway.envoyproxy.io
+      kind: Backend
+      name: backend-insecure-tls-verify
+  validation:
+    wellKnownCACertificates: System
+    hostname: example.com
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: Backend
+metadata:
+  name: backend-insecure-tls-verify
+  namespace: gateway-conformance-infra
+spec:
+  endpoints:
+    - fqdn:
+        hostname: tls-backend-2.gateway-conformance-infra.svc.cluster.local
+        port: 443
+  tls:
+    insecureSkipVerify: true
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: http-with-backend-insecure-skip-verify
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: same-namespace
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /backend-tls-skip-verify
+      backendRefs:
+        - name: backend-insecure-tls-verify
+          group: gateway.envoyproxy.io
+          kind: Backend
diff --git a/test/e2e/testdata/envoyproxy-stat-name.yaml b/test/e2e/testdata/envoyproxy-stat-name.yaml
new file mode 100644
index 000000000..de1593077
--- /dev/null
+++ b/test/e2e/testdata/envoyproxy-stat-name.yaml
@@ -0,0 +1,57 @@
+apiVersion: gateway.networking.k8s.io/v1
+kind: Gateway
+metadata:
+  name: stat-name-gtw
+  namespace: gateway-conformance-infra
+spec:
+  gatewayClassName: "{GATEWAY_CLASS_NAME}"
+  listeners:
+    - name: http
+      port: 80
+      protocol: HTTP
+      allowedRoutes:
+        namespaces:
+          from: Same
+  infrastructure:
+    parametersRef:
+      group: gateway.envoyproxy.io
+      kind: EnvoyProxy
+      name: stat-name-ep
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: stat-name-ep
+  namespace: gateway-conformance-infra
+spec:
+  ipFamily: IPv4
+  telemetry:
+    metrics:
+      clusterStatName: "%ROUTE_NAMESPACE%/%ROUTE_NAME%/%BACKEND_REFS%"
+  shutdown:
+    drainTimeout: 5s
+    minDrainDuration: 1s
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: stat-name-route
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: stat-name-gtw
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /foo
+      backendRefs:
+        - name: infra-backend-v1
+          port: 8080
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /bar
+      backendRefs:
+        - name: infra-backend-v1
+          port: 8080
diff --git a/test/e2e/tests/backend_tls.go b/test/e2e/tests/backend_tls.go
index 61caf2749..54b77b5be 100644
--- a/test/e2e/tests/backend_tls.go
+++ b/test/e2e/tests/backend_tls.go
@@ -90,5 +90,24 @@ var BackendTLSTest = suite.ConformanceTest{
 
 			http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
 		})
+
+		t.Run("with CA mismatch and skip tls verify", func(t *testing.T) {
+			ns := "gateway-conformance-infra"
+			routeNN := types.NamespacedName{Name: "http-with-backend-insecure-skip-verify", Namespace: ns}
+			gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
+			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+			expectedResponse := http.ExpectedResponse{
+				Request: http.Request{
+					Path: "/backend-tls-skip-verify",
+				},
+				Response: http.Response{
+					StatusCode: 200, // Bad Request: Client sent an HTTP request to an HTTPS server
+				},
+				Namespace: ns,
+			}
+
+			http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+		})
 	},
 }
diff --git a/test/e2e/tests/stat_name.go b/test/e2e/tests/stat_name.go
new file mode 100644
index 000000000..99441a516
--- /dev/null
+++ b/test/e2e/tests/stat_name.go
@@ -0,0 +1,86 @@
+// Copyright Envoy Gateway Authors
+// SPDX-License-Identifier: Apache-2.0
+// The full text of the Apache license is available in the LICENSE file at
+// the root of the repo.
+
+//go:build e2e
+
+package tests
+
+import (
+	"context"
+	"testing"
+	"time"
+
+	"github.com/prometheus/common/model"
+	"k8s.io/apimachinery/pkg/types"
+	"k8s.io/apimachinery/pkg/util/wait"
+	httputils "sigs.k8s.io/gateway-api/conformance/utils/http"
+	"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
+	"sigs.k8s.io/gateway-api/conformance/utils/suite"
+	"sigs.k8s.io/gateway-api/conformance/utils/tlog"
+
+	"github.com/envoyproxy/gateway/test/utils/prometheus"
+)
+
+func init() {
+	ConformanceTests = append(ConformanceTests, StatNameTest)
+}
+
+var StatNameTest = suite.ConformanceTest{
+	ShortName:   "StatName",
+	Description: "Make sure metric is working",
+	Manifests:   []string{"testdata/envoyproxy-stat-name.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		ns := "gateway-conformance-infra"
+		routeNN := types.NamespacedName{Name: "stat-name-route", Namespace: ns}
+		gwNN := types.NamespacedName{Name: "stat-name-gtw", Namespace: ns}
+		gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+		t.Run("prometheus", func(t *testing.T) {
+			expectedResponse := httputils.ExpectedResponse{
+				Request: httputils.Request{
+					Path: "/foo",
+				},
+				Response: httputils.Response{
+					StatusCode: 200,
+				},
+				Namespace: ns,
+			}
+			// make sure listener is ready
+			httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+
+			expectedResponse = httputils.ExpectedResponse{
+				Request: httputils.Request{
+					Path: "/bar",
+				},
+				Response: httputils.Response{
+					StatusCode: 200,
+				},
+				Namespace: ns,
+			}
+			// make sure listener is ready
+			httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+
+			// make sure that a metrics for alt_stat_name exists in test gateway and they collapse stats from multiple clusters
+			// expect to find 2 cluster members, since there are two routes with the same alt_stat_name and each cluster has a single member
+			if err := wait.PollUntilContextTimeout(context.TODO(), 3*time.Second, time.Minute, true, func(ctx context.Context) (done bool, err error) {
+				v, err := prometheus.QueryPrometheus(suite.Client, `envoy_cluster_membership_healthy{envoy_cluster_name="gateway-conformance-infra/stat-name-route/gateway-conformance-infra/infra-backend-v1"}`)
+				if err != nil {
+					tlog.Logf(t, "failed to query prometheus: %v", err)
+					return false, err
+				}
+				if v != nil && v.Type() == model.ValVector {
+					vectorVal := v.(model.Vector)
+					if len(vectorVal) == 1 && vectorVal[0].Value == 2 {
+						tlog.Logf(t, "got expected value: %v", v)
+						return true, nil
+					}
+				}
+				return false, nil
+			}); err != nil {
+				t.Errorf("failed to get expected response for the last (fourth) request: %v", err)
+			}
+		})
+	},
+}
diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml
index 3da0d85af..fb397553a 100644
--- a/test/helm/gateway-crds-helm/all.out.yaml
+++ b/test/helm/gateway-crds-helm/all.out.yaml
@@ -17469,7 +17469,8 @@ spec:
               tls:
                 description: |-
                   TLS defines the TLS settings for the backend.
-                  Only supported for DynamicResolver backends.
+                  TLS.CACertificateRefs and TLS.WellKnownCACertificates can only be specified for DynamicResolver backends.
+                  TLS.InsecureSkipVerify can be specified for any Backends
                 properties:
                   caCertificateRefs:
                     description: |-
@@ -17547,10 +17548,12 @@ spec:
                   rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs)
                     > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates
                     != "")'
-                - message: must specify either CACertificateRefs or WellKnownCACertificates
-                  rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs)
-                    > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates
-                    != "")
+                - message: must not contain either CACertificateRefs or WellKnownCACertificates
+                    when InsecureSkipVerify is enabled
+                  rule: '!((has(self.insecureSkipVerify) && self.insecureSkipVerify)
+                    && ((has(self.caCertificateRefs) && size(self.caCertificateRefs)
+                    > 0) || (has(self.wellKnownCACertificates) && self.wellKnownCACertificates
+                    != "")))'
               type:
                 default: Endpoints
                 description: Type defines the type of the backend. Defaults to "Endpoints"
@@ -36126,6 +36129,21 @@ spec:
                     description: Metrics defines metrics configuration for managed
                       proxies.
                     properties:
+                      clusterStatName:
+                        description: |-
+                          ClusterStatName defines the value of cluster alt_stat_name, determining how cluster stats are named.
+                          For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html
+                          The supported operators for this pattern are:
+                          %ROUTE_NAME%: name of Gateway API xRoute resource
+                          %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+                          %ROUTE_KIND%: kind of Gateway API xRoute resource
+                          %ROUTE_RULE_NAME%: name of the Gateway API xRoute section
+                          %ROUTE_RULE_NUMBER%: name of the Gateway API xRoute section
+                          %BACKEND_REFS%: names of all backends referenced in <NAMESPACE>/<NAME>|<NAMESPACE>/<NAME>|... format
+                          Only xDS Clusters created for HTTPRoute and GRPCRoute are currently supported.
+                          Default: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/rule/%ROUTE_RULE_NUMBER%
+                          Example: httproute/my-ns/my-route/rule/0
+                        type: string
                       enablePerEndpointStats:
                         description: |-
                           EnablePerEndpointStats enables per endpoint envoy stats metrics.
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 c045a76b9..4ed996f94 100644
--- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
+++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
@@ -157,7 +157,8 @@ spec:
               tls:
                 description: |-
                   TLS defines the TLS settings for the backend.
-                  Only supported for DynamicResolver backends.
+                  TLS.CACertificateRefs and TLS.WellKnownCACertificates can only be specified for DynamicResolver backends.
+                  TLS.InsecureSkipVerify can be specified for any Backends
                 properties:
                   caCertificateRefs:
                     description: |-
@@ -235,10 +236,12 @@ spec:
                   rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs)
                     > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates
                     != "")'
-                - message: must specify either CACertificateRefs or WellKnownCACertificates
-                  rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs)
-                    > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates
-                    != "")
+                - message: must not contain either CACertificateRefs or WellKnownCACertificates
+                    when InsecureSkipVerify is enabled
+                  rule: '!((has(self.insecureSkipVerify) && self.insecureSkipVerify)
+                    && ((has(self.caCertificateRefs) && size(self.caCertificateRefs)
+                    > 0) || (has(self.wellKnownCACertificates) && self.wellKnownCACertificates
+                    != "")))'
               type:
                 default: Endpoints
                 description: Type defines the type of the backend. Defaults to "Endpoints"
@@ -18814,6 +18817,21 @@ spec:
                     description: Metrics defines metrics configuration for managed
                       proxies.
                     properties:
+                      clusterStatName:
+                        description: |-
+                          ClusterStatName defines the value of cluster alt_stat_name, determining how cluster stats are named.
+                          For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html
+                          The supported operators for this pattern are:
+                          %ROUTE_NAME%: name of Gateway API xRoute resource
+                          %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+                          %ROUTE_KIND%: kind of Gateway API xRoute resource
+                          %ROUTE_RULE_NAME%: name of the Gateway API xRoute section
+                          %ROUTE_RULE_NUMBER%: name of the Gateway API xRoute section
+                          %BACKEND_REFS%: names of all backends referenced in <NAMESPACE>/<NAME>|<NAMESPACE>/<NAME>|... format
+                          Only xDS Clusters created for HTTPRoute and GRPCRoute are currently supported.
+                          Default: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/rule/%ROUTE_RULE_NUMBER%
+                          Example: httproute/my-ns/my-route/rule/0
+                        type: string
                       enablePerEndpointStats:
                         description: |-
                           EnablePerEndpointStats enables per endpoint envoy stats metrics.