Repository: envoyproxy/gateway
Pull request #3739 (2024-07-03 10:30:51)

docs: CEL Expressions for Access Logging
fix: https://github.com/envoyproxy/gateway/issues/3734


Patch:
diff --git a/api/v1alpha1/loadbalancer_types.go b/api/v1alpha1/loadbalancer_types.go
index 9fdaf26d5..3fd144bdf 100644
--- a/api/v1alpha1/loadbalancer_types.go
+++ b/api/v1alpha1/loadbalancer_types.go
@@ -71,7 +71,6 @@ type ConsistentHash struct {
 	// Cookie configures the cookie hash policy when the consistent hash type is set to Cookie.
 	//
 	// +optional
-	// +notImplementedHide
 	Cookie *Cookie `json:"cookie,omitempty"`
 
 	// The table size for consistent hashing, must be prime number limited to 5000011.
@@ -103,12 +102,10 @@ type Cookie struct {
 	// Max-Age attribute value.
 	//
 	// +optional
-	// +notImplementedHide
 	TTL *metav1.Duration `json:"ttl,omitempty"`
 	// Additional Attributes to set for the generated cookie.
 	//
 	// +optional
-	// +notImplementedHide
 	Attributes map[string]string `json:"attributes,omitempty"`
 }
 
diff --git a/api/v1alpha1/policy_helpers.go b/api/v1alpha1/policy_helpers.go
index 31223bf10..f1bc16e17 100644
--- a/api/v1alpha1/policy_helpers.go
+++ b/api/v1alpha1/policy_helpers.go
@@ -10,18 +10,33 @@ import (
 )
 
 type PolicyTargetReferences struct {
-	// TargetRef is the name of the Gateway resource this policy
-	// is being attached to.
-	// This Policy and the TargetRef MUST be in the same namespace
-	// for this Policy to have effect and be applied to the Gateway.
-	// TargetRef
+	// TargetRef is the name of the resource this policy is being attached to.
+	// This policy and the TargetRef MUST be in the same namespace for this
+	// Policy to have effect
 	//
-	// Deprecated: use targetRefs instead
+	// Deprecated: use targetRefs/targetSelectors instead
 	TargetRef *gwapiv1a2.LocalPolicyTargetReferenceWithSectionName `json:"targetRef,omitempty"`
 
 	// TargetRefs are the names of the Gateway resources this policy
 	// is being attached to.
 	TargetRefs []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs,omitempty"`
+
+	// TargetSelectors allow targeting resources for this policy based on labels
+	TargetSelectors []TargetSelector `json:"targetSelectors,omitempty"`
+}
+
+// +kubebuilder:validation:XValidation:rule="has(self.group) ? self.group == 'gateway.networking.k8s.io' : true ", message="group must be gateway.networking.k8s.io"
+type TargetSelector struct {
+	// Group is the group that this selector targets. Defaults to gateway.networking.k8s.io
+	//
+	// +kubebuilder:default:="gateway.networking.k8s.io"
+	Group *gwapiv1a2.Group `json:"group,omitempty"`
+
+	// Kind is the resource kind that this selector targets.
+	Kind gwapiv1a2.Kind `json:"kind"`
+
+	// MatchLabels are the set of label selectors for identifying the targeted resource
+	MatchLabels map[string]string `json:"matchLabels"`
 }
 
 func (p PolicyTargetReferences) GetTargetRefs() []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName {
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 56a090358..6e55a9d29 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -3628,6 +3628,13 @@ func (in *PolicyTargetReferences) DeepCopyInto(out *PolicyTargetReferences) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
+	if in.TargetSelectors != nil {
+		in, out := &in.TargetSelectors, &out.TargetSelectors
+		*out = make([]TargetSelector, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyTargetReferences.
@@ -4724,6 +4731,33 @@ func (in *TLSSettings) DeepCopy() *TLSSettings {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TargetSelector) DeepCopyInto(out *TargetSelector) {
+	*out = *in
+	if in.Group != nil {
+		in, out := &in.Group, &out.Group
+		*out = new(apisv1.Group)
+		**out = **in
+	}
+	if in.MatchLabels != nil {
+		in, out := &in.MatchLabels, &out.MatchLabels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetSelector.
+func (in *TargetSelector) DeepCopy() *TargetSelector {
+	if in == nil {
+		return nil
+	}
+	out := new(TargetSelector)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Timeout) DeepCopyInto(out *Timeout) {
 	*out = *in
diff --git a/charts/gateway-addons-helm/README.md b/charts/gateway-addons-helm/README.md
index ff47a1e47..dc364b5d1 100644
--- a/charts/gateway-addons-helm/README.md
+++ b/charts/gateway-addons-helm/README.md
@@ -112,6 +112,7 @@ To uninstall the chart:
 | opentelemetry-collector.config.processors.attributes.actions[0].value | string | `"k8s.pod.name, k8s.namespace.name"` |  |
 | opentelemetry-collector.config.receivers.otlp.protocols.grpc.endpoint | string | `"${env:MY_POD_IP}:4317"` |  |
 | opentelemetry-collector.config.receivers.otlp.protocols.http.endpoint | string | `"${env:MY_POD_IP}:4318"` |  |
+| opentelemetry-collector.config.receivers.zipkin.endpoint | string | `"${env:MY_POD_IP}:9411"` |  |
 | opentelemetry-collector.config.service.extensions[0] | string | `"health_check"` |  |
 | opentelemetry-collector.config.service.pipelines.logs.exporters[0] | string | `"loki"` |  |
 | opentelemetry-collector.config.service.pipelines.logs.processors[0] | string | `"attributes"` |  |
@@ -120,6 +121,7 @@ To uninstall the chart:
 | opentelemetry-collector.config.service.pipelines.metrics.receivers[0] | string | `"otlp"` |  |
 | opentelemetry-collector.config.service.pipelines.traces.exporters[0] | string | `"otlp"` |  |
 | opentelemetry-collector.config.service.pipelines.traces.receivers[0] | string | `"otlp"` |  |
+| opentelemetry-collector.config.service.pipelines.traces.receivers[1] | string | `"zipkin"` |  |
 | opentelemetry-collector.enabled | bool | `false` |  |
 | opentelemetry-collector.fullnameOverride | string | `"otel-collector"` |  |
 | opentelemetry-collector.mode | string | `"deployment"` |  |
diff --git a/charts/gateway-addons-helm/values.yaml b/charts/gateway-addons-helm/values.yaml
index cc17ef523..eddf933c1 100644
--- a/charts/gateway-addons-helm/values.yaml
+++ b/charts/gateway-addons-helm/values.yaml
@@ -203,6 +203,8 @@ opentelemetry-collector:
             # Loki will convert this to k8s_pod_name label.
             value: k8s.pod.name, k8s.namespace.name
     receivers:
+      zipkin:
+        endpoint: ${env:MY_POD_IP}:9411
       otlp:
         protocols:
           grpc:
@@ -230,3 +232,4 @@ opentelemetry-collector:
             - otlp
           receivers:
             - otlp
+            - zipkin
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
index 7d7e7c968..d779a2d83 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
@@ -917,14 +917,12 @@ spec:
                 type: object
               targetRef:
                 description: |-
-                  TargetRef is the name of the Gateway resource this policy
-                  is being attached to.
-                  This Policy and the TargetRef MUST be in the same namespace
-                  for this Policy to have effect and be applied to the Gateway.
-                  TargetRef
+                  TargetRef is the name of the resource this policy is being attached to.
+                  This policy and the TargetRef MUST be in the same namespace for this
+                  Policy to have effect
 
 
-                  Deprecated: use targetRefs instead
+                  Deprecated: use targetRefs/targetSelectors instead
                 properties:
                   group:
                     description: Group is the group of the target resource.
@@ -1024,6 +1022,39 @@ spec:
                   - name
                   type: object
                 type: array
+              targetSelectors:
+                description: TargetSelectors allow targeting resources for this policy
+                  based on labels
+                items:
+                  properties:
+                    group:
+                      default: gateway.networking.k8s.io
+                      description: Group is the group that this selector targets.
+                        Defaults to gateway.networking.k8s.io
+                      maxLength: 253
+                      pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
+                    kind:
+                      description: Kind is the resource kind that this selector targets.
+                      maxLength: 63
+                      minLength: 1
+                      pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                      type: string
+                    matchLabels:
+                      additionalProperties:
+                        type: string
+                      description: MatchLabels are the set of label selectors for
+                        identifying the targeted resource
+                      type: object
+                  required:
+                  - kind
+                  - matchLabels
+                  type: object
+                  x-kubernetes-validations:
+                  - message: group must be gateway.networking.k8s.io
+                    rule: 'has(self.group) ? self.group == ''gateway.networking.k8s.io''
+                      : true '
+                type: array
               tcpKeepalive:
                 description: |-
                   TcpKeepalive settings associated with the upstream client connection.
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml
index 218c1cf2e..2e2224ecc 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml
@@ -328,14 +328,12 @@ spec:
                 type: object
               targetRef:
                 description: |-
-                  TargetRef is the name of the Gateway resource this policy
-                  is being attached to.
-                  This Policy and the TargetRef MUST be in the same namespace
-                  for this Policy to have effect and be applied to the Gateway.
-                  TargetRef
+                  TargetRef is the name of the resource this policy is being attached to.
+                  This policy and the TargetRef MUST be in the same namespace for this
+                  Policy to have effect
 
 
-                  Deprecated: use targetRefs instead
+                  Deprecated: use targetRefs/targetSelectors instead
                 properties:
                   group:
                     description: Group is the group of the target resource.
@@ -435,6 +433,39 @@ spec:
                   - name
                   type: object
                 type: array
+              targetSelectors:
+                description: TargetSelectors allow targeting resources for this policy
+                  based on labels
+                items:
+                  properties:
+                    group:
+                      default: gateway.networking.k8s.io
+                      description: Group is the group that this selector targets.
+                        Defaults to gateway.networking.k8s.io
+                      maxLength: 253
+                      pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
+                    kind:
+                      description: Kind is the resource kind that this selector targets.
+                      maxLength: 63
+                      minLength: 1
+                      pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                      type: string
+                    matchLabels:
+                      additionalProperties:
+                        type: string
+                      description: MatchLabels are the set of label selectors for
+                        identifying the targeted resource
+                      type: object
+                  required:
+                  - kind
+                  - matchLabels
+                  type: object
+                  x-kubernetes-validations:
+                  - message: group must be gateway.networking.k8s.io
+                    rule: 'has(self.group) ? self.group == ''gateway.networking.k8s.io''
+                      : true '
+                type: array
               tcpKeepalive:
                 description: |-
                   TcpKeepalive settings associated with the downstream client connection.
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
index 92a0c9def..0b2576030 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
@@ -194,14 +194,12 @@ spec:
                 type: array
               targetRef:
                 description: |-
-                  TargetRef is the name of the Gateway resource this policy
-                  is being attached to.
-                  This Policy and the TargetRef MUST be in the same namespace
-                  for this Policy to have effect and be applied to the Gateway.
-                  TargetRef
+                  TargetRef is the name of the resource this policy is being attached to.
+                  This policy and the TargetRef MUST be in the same namespace for this
+                  Policy to have effect
 
 
-                  Deprecated: use targetRefs instead
+                  Deprecated: use targetRefs/targetSelectors instead
                 properties:
                   group:
                     description: Group is the group of the target resource.
@@ -301,6 +299,39 @@ spec:
                   - name
                   type: object
                 type: array
+              targetSelectors:
+                description: TargetSelectors allow targeting resources for this policy
+                  based on labels
+                items:
+                  properties:
+                    group:
+                      default: gateway.networking.k8s.io
+                      description: Group is the group that this selector targets.
+                        Defaults to gateway.networking.k8s.io
+                      maxLength: 253
+                      pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
+                    kind:
+                      description: Kind is the resource kind that this selector targets.
+                      maxLength: 63
+                      minLength: 1
+                      pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                      type: string
+                    matchLabels:
+                      additionalProperties:
+                        type: string
+                      description: MatchLabels are the set of label selectors for
+                        identifying the targeted resource
+                      type: object
+                  required:
+                  - kind
+                  - matchLabels
+                  type: object
+                  x-kubernetes-validations:
+                  - message: group must be gateway.networking.k8s.io
+                    rule: 'has(self.group) ? self.group == ''gateway.networking.k8s.io''
+                      : true '
+                type: array
               wasm:
                 description: |-
                   Wasm is a list of Wasm extensions to be loaded by the Gateway.
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
index 29c2cb135..e5c0b7fc9 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
@@ -988,14 +988,12 @@ spec:
                 type: object
               targetRef:
                 description: |-
-                  TargetRef is the name of the Gateway resource this policy
-                  is being attached to.
-                  This Policy and the TargetRef MUST be in the same namespace
-                  for this Policy to have effect and be applied to the Gateway.
-                  TargetRef
+                  TargetRef is the name of the resource this policy is being attached to.
+                  This policy and the TargetRef MUST be in the same namespace for this
+                  Policy to have effect
 
 
-                  Deprecated: use targetRefs instead
+                  Deprecated: use targetRefs/targetSelectors instead
                 properties:
                   group:
                     description: Group is the group of the target resource.
@@ -1095,6 +1093,39 @@ spec:
                   - name
                   type: object
                 type: array
+              targetSelectors:
+                description: TargetSelectors allow targeting resources for this policy
+                  based on labels
+                items:
+                  properties:
+                    group:
+                      default: gateway.networking.k8s.io
+                      description: Group is the group that this selector targets.
+                        Defaults to gateway.networking.k8s.io
+                      maxLength: 253
+                      pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                      type: string
+                    kind:
+                      description: Kind is the resource kind that this selector targets.
+                      maxLength: 63
+                      minLength: 1
+                      pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                      type: string
+                    matchLabels:
+                      additionalProperties:
+                        type: string
+                      description: MatchLabels are the set of label selectors for
+                        identifying the targeted resource
+                      type: object
+                  required:
+                  - kind
+                  - matchLabels
+                  type: object
+                  x-kubernetes-validations:
+                  - message: group must be gateway.networking.k8s.io
+                    rule: 'has(self.group) ? self.group == ''gateway.networking.k8s.io''
+                      : true '
+                type: array
             type: object
             x-kubernetes-validations:
             - message: either targetRef or targetRefs must be used
diff --git a/internal/cmd/version/version.go b/internal/cmd/version/version.go
index 37d3bb174..d1a8ddb80 100644
--- a/internal/cmd/version/version.go
+++ b/internal/cmd/version/version.go
@@ -9,6 +9,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"runtime"
 	"runtime/debug"
 	"strings"
 
@@ -22,6 +23,7 @@ type Info struct {
 	GatewayAPIVersion   string `json:"gatewayAPIVersion"`
 	EnvoyProxyVersion   string `json:"envoyProxyVersion"`
 	GitCommitID         string `json:"gitCommitID"`
+	GolangVersion       string `json:"golangVersion"`
 }
 
 func Get() Info {
@@ -30,6 +32,7 @@ func Get() Info {
 		GatewayAPIVersion:   gatewayAPIVersion,
 		EnvoyProxyVersion:   envoyProxyVersion,
 		GitCommitID:         gitCommitID,
+		GolangVersion:       runtime.Version(),
 	}
 }
 
@@ -68,6 +71,7 @@ func Print(w io.Writer, format string) error {
 		_, _ = fmt.Fprintf(w, "ENVOY_PROXY_VERSION: %s\n", v.EnvoyProxyVersion)
 		_, _ = fmt.Fprintf(w, "GATEWAYAPI_VERSION: %s\n", v.GatewayAPIVersion)
 		_, _ = fmt.Fprintf(w, "GIT_COMMIT_ID: %s\n", v.GitCommitID)
+		_, _ = fmt.Fprintf(w, "GOLANG_VERSION: %s\n", v.GolangVersion)
 	}
 
 	return nil
diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go
index bcc6a5507..6babdfa81 100644
--- a/internal/gatewayapi/backendtrafficpolicy.go
+++ b/internal/gatewayapi/backendtrafficpolicy.go
@@ -73,7 +73,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv
 	// Process the policies targeting xRoutes
 	for _, currPolicy := range backendTrafficPolicies {
 		policyName := utils.NamespacedName(currPolicy)
-		targetRefs := currPolicy.Spec.GetTargetRefs()
+		targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, routes)
 		for _, currTarget := range targetRefs {
 			if currTarget.Kind != KindGateway {
 				policy, found := handledPolicies[policyName]
@@ -147,7 +147,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv
 	// Process the policies targeting Gateways
 	for _, currPolicy := range backendTrafficPolicies {
 		policyName := utils.NamespacedName(currPolicy)
-		targetRefs := currPolicy.Spec.GetTargetRefs()
+		targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways)
 		for _, currTarget := range targetRefs {
 			if currTarget.Kind == KindGateway {
 				policy, found := handledPolicies[policyName]
@@ -864,6 +864,8 @@ func (t *Translator) buildConsistentHashLoadBalancer(policy *egv1a1.BackendTraff
 		consistentHash.Header = &ir.Header{
 			Name: policy.Spec.LoadBalancer.ConsistentHash.Header.Name,
 		}
+	case egv1a1.CookieConsistentHashType:
+		consistentHash.Cookie = policy.Spec.LoadBalancer.ConsistentHash.Cookie
 	}
 
 	return consistentHash, nil
diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go
index cde236dbc..7a25a6613 100644
--- a/internal/gatewayapi/clienttrafficpolicy.go
+++ b/internal/gatewayapi/clienttrafficpolicy.go
@@ -70,6 +70,9 @@ func (t *Translator) ProcessClientTrafficPolicies(
 	// before policy with no section so below loops can be flattened into 1.
 	for _, currPolicy := range clientTrafficPolicies {
 		policyName := utils.NamespacedName(currPolicy)
+		// This loop only handles policies that target a specific section. When
+		// targeting a policy with a selector, it's not possible to specify a SectionName
+		// so there's no need to try to match targets with selectors
 		targetRefs := currPolicy.Spec.GetTargetRefs()
 		for _, currTarget := range targetRefs {
 			if hasSectionName(&currTarget) {
@@ -165,7 +168,7 @@ func (t *Translator) ProcessClientTrafficPolicies(
 	// Policy with no section set (targeting all sections)
 	for _, currPolicy := range clientTrafficPolicies {
 		policyName := utils.NamespacedName(currPolicy)
-		targetRefs := currPolicy.Spec.GetTargetRefs()
+		targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways)
 		for _, currTarget := range targetRefs {
 			if !hasSectionName(&currTarget) {
 
diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go
index 5baecbcb5..9d1b0f922 100644
--- a/internal/gatewayapi/envoyextensionpolicy.go
+++ b/internal/gatewayapi/envoyextensionpolicy.go
@@ -74,7 +74,7 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv
 	// Process the policies targeting xRoutes
 	for _, currPolicy := range envoyExtensionPolicies {
 		policyName := utils.NamespacedName(currPolicy)
-		targetRefs := currPolicy.Spec.GetTargetRefs()
+		targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, routes)
 		for _, currTarget := range targetRefs {
 			if currTarget.Kind != KindGateway {
 				policy, found := handledPolicies[policyName]
@@ -148,7 +148,7 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv
 	// Process the policies targeting Gateways
 	for _, currPolicy := range envoyExtensionPolicies {
 		policyName := utils.NamespacedName(currPolicy)
-		targetRefs := currPolicy.Spec.GetTargetRefs()
+		targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways)
 		for _, currTarget := range targetRefs {
 			if currTarget.Kind == KindGateway {
 				policy, found := handledPolicies[policyName]
diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go
index 408a40ab0..269c968b4 100644
--- a/internal/gatewayapi/helpers.go
+++ b/internal/gatewayapi/helpers.go
@@ -9,11 +9,15 @@ import (
 	"errors"
 	"fmt"
 	"net"
+	"slices"
 	"strings"
 
 	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/types"
+	"k8s.io/apimachinery/pkg/util/sets"
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
@@ -495,3 +499,54 @@ func irConfigName(policy client.Object) string {
 		strings.ToLower(policy.GetObjectKind().GroupVersionKind().Kind),
 		utils.NamespacedName(policy).String())
 }
+
+type targetRefWithTimestamp struct {
+	gwapiv1a2.LocalPolicyTargetReferenceWithSectionName
+	CreationTimestamp metav1.Time
+}
+
+func getPolicyTargetRefs[T client.Object](policy egv1a1.PolicyTargetReferences, potentialTargets []T) []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName {
+	dedup := sets.New[targetRefWithTimestamp]()
+	for _, currSelector := range policy.TargetSelectors {
+		labelSelector := labels.SelectorFromSet(currSelector.MatchLabels)
+		for _, obj := range potentialTargets {
+			gvk := obj.GetObjectKind().GroupVersionKind()
+			if gvk.Kind != string(currSelector.Kind) ||
+				gvk.Group != string(ptr.Deref(currSelector.Group, gwapiv1a2.GroupName)) {
+				continue
+			}
+
+			if labelSelector.Matches(labels.Set(obj.GetLabels())) {
+				dedup.Insert(targetRefWithTimestamp{
+					CreationTimestamp: obj.GetCreationTimestamp(),
+					LocalPolicyTargetReferenceWithSectionName: gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+						LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+							Group: gwapiv1a2.Group(gvk.Group),
+							Kind:  gwapiv1a2.Kind(gvk.Kind),
+							Name:  gwapiv1a2.ObjectName(obj.GetName()),
+						},
+					},
+				})
+			}
+		}
+	}
+	selectorsList := dedup.UnsortedList()
+	slices.SortFunc(selectorsList, func(i, j targetRefWithTimestamp) int {
+		return i.CreationTimestamp.Compare(j.CreationTimestamp.Time)
+	})
+	ret := []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{}
+	for _, v := range selectorsList {
+		ret = append(ret, v.LocalPolicyTargetReferenceWithSectionName)
+	}
+	// Plain targetRefs in the policy don't have an associated creation timestamp, but can still refer
+	// to targets that were already found via the selectors. Only add them to the returned list if
+	// they are not yet there. Always add them at the end.
+	fastLookup := sets.New(ret...)
+	for _, v := range policy.GetTargetRefs() {
+		if !fastLookup.Has(v) {
+			ret = append(ret, v)
+		}
+	}
+
+	return ret
+}
diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go
index 25afaacee..1bef8ca52 100644
--- a/internal/gatewayapi/listener.go
+++ b/internal/gatewayapi/listener.go
@@ -466,7 +466,7 @@ func (t *Translator) processBackendRefs(backendRefs []egv1a1.BackendRef, namespa
 			return nil, err
 		}
 
-		ds := t.processServiceDestinationSetting(ref.BackendObjectReference, ns, ir.GRPC, resources, envoyProxy)
+		ds := t.processServiceDestinationSetting(ref.BackendObjectReference, ns, ir.TCP, resources, envoyProxy)
 		result = append(result, ds)
 	}
 	if len(result) == 0 {
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index 98e998c7f..c6719015d 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -1307,10 +1307,14 @@ func (t *Translator) processServiceDestinationSetting(
 		}
 	}
 
-	// support HTTPRouteBackendProtocolH2C
-	if servicePort.AppProtocol != nil &&
-		*servicePort.AppProtocol == "kubernetes.io/h2c" {
-		protocol = ir.HTTP2
+	// support HTTPRouteBackendProtocolH2C/GRPC
+	if servicePort.AppProtocol != nil {
+		switch *servicePort.AppProtocol {
+		case "kubernetes.io/h2c":
+			protocol = ir.HTTP2
+		case "grpc":
+			protocol = ir.GRPC
+		}
 	}
 
 	// Route to endpoints by default
diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go
index 470113b60..57153bc7e 100644
--- a/internal/gatewayapi/securitypolicy.go
+++ b/internal/gatewayapi/securitypolicy.go
@@ -85,7 +85,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security
 	// Process the policies targeting xRoutes
 	for _, currPolicy := range securityPolicies {
 		policyName := utils.NamespacedName(currPolicy)
-		targetRefs := currPolicy.Spec.GetTargetRefs()
+		targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, routes)
 		for _, currTarget := range targetRefs {
 			if currTarget.Kind != KindGateway {
 				var (
@@ -163,7 +163,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security
 	// Process the policies targeting Gateways
 	for _, currPolicy := range securityPolicies {
 		policyName := utils.NamespacedName(currPolicy)
-		targetRefs := currPolicy.Spec.GetTargetRefs()
+		targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways)
 		for _, currTarget := range targetRefs {
 			if currTarget.Kind == KindGateway {
 				var (
diff --git a/internal/gatewayapi/status/gateway.go b/internal/gatewayapi/status/gateway.go
index e9c204066..f891f8c40 100644
--- a/internal/gatewayapi/status/gateway.go
+++ b/internal/gatewayapi/status/gateway.go
@@ -96,8 +96,9 @@ func UpdateGatewayStatusProgrammedCondition(gw *gwapiv1.Gateway, svc *corev1.Ser
 	} else {
 		gw.Status.Addresses = nil
 	}
+
 	// Update the programmed condition.
-	gw.Status.Conditions = MergeConditions(gw.Status.Conditions, computeGatewayProgrammedCondition(gw, deployment))
+	updateGatewayProgrammedCondition(gw, deployment)
 }
 
 func SetGatewayListenerStatusCondition(gateway *gwapiv1.Gateway, listenerStatusIdx int,
@@ -128,26 +129,45 @@ func computeGatewayAcceptedCondition(gw *gwapiv1.Gateway, accepted bool) metav1.
 	}
 }
 
-// computeGatewayProgrammedCondition computes the Gateway Programmed status condition.
+const (
+	messageAddressNotAssigned  = "No addresses have been assigned to the Gateway"
+	messageFmtTooManyAddresses = "Too many addresses (%d) have been assigned to the Gateway, the maximum number of addresses is 16"
+	messageNoResources         = "Deployment replicas unavailable"
+	messageFmtProgrammed       = "Address assigned to the Gateway, %d/%d envoy Deployment replicas available"
+)
+
+// updateGatewayProgrammedCondition computes the Gateway Programmed status condition.
 // Programmed condition surfaces true when the Envoy Deployment status is ready.
-func computeGatewayProgrammedCondition(gw *gwapiv1.Gateway, deployment *appsv1.Deployment) metav1.Condition {
+func updateGatewayProgrammedCondition(gw *gwapiv1.Gateway, deployment *appsv1.Deployment) {
 	if len(gw.Status.Addresses) == 0 {
-		return newCondition(string(gwapiv1.GatewayConditionProgrammed), metav1.ConditionFalse,
-			string(gwapiv1.GatewayReasonAddressNotAssigned),
-			"No addresses have been assigned to the Gateway", time.Now(), gw.Generation)
+		gw.Status.Conditions = MergeConditions(gw.Status.Conditions,
+			newCondition(string(gwapiv1.GatewayConditionProgrammed), metav1.ConditionFalse, string(gwapiv1.GatewayReasonAddressNotAssigned),
+				messageAddressNotAssigned, time.Now(), gw.Generation))
+		return
+	}
+
+	if len(gw.Status.Addresses) > 16 {
+		gw.Status.Conditions = MergeConditions(gw.Status.Conditions,
+			newCondition(string(gwapiv1.GatewayConditionProgrammed), metav1.ConditionFalse, string(gwapiv1.GatewayReasonInvalid),
+				fmt.Sprintf(messageFmtTooManyAddresses, len(gw.Status.Addresses)), time.Now(), gw.Generation))
+
+		// Truncate the addresses to 16
+		// so that the status can be updated successfully.
+		gw.Status.Addresses = gw.Status.Addresses[:16]
+		return
 	}
 
 	// If there are no available replicas for the Envoy Deployment, don't
 	// mark the Gateway as ready yet.
 
 	if deployment == nil || deployment.Status.AvailableReplicas == 0 {
-		return newCondition(string(gwapiv1.GatewayConditionProgrammed), metav1.ConditionFalse,
-			string(gwapiv1.GatewayReasonNoResources),
-			"Deployment replicas unavailable", time.Now(), gw.Generation)
+		gw.Status.Conditions = MergeConditions(gw.Status.Conditions,
+			newCondition(string(gwapiv1.GatewayConditionProgrammed), metav1.ConditionFalse, string(gwapiv1.GatewayReasonNoResources),
+				messageNoResources, time.Now(), gw.Generation))
+		return
 	}
 
-	message := fmt.Sprintf("Address assigned to the Gateway, %d/%d envoy Deployment replicas available",
-		deployment.Status.AvailableReplicas, deployment.Status.Replicas)
-	return newCondition(string(gwapiv1.GatewayConditionProgrammed), metav1.ConditionTrue,
-		string(gwapiv1.GatewayConditionProgrammed), message, time.Now(), gw.Generation)
+	gw.Status.Conditions = MergeConditions(gw.Status.Conditions,
+		newCondition(string(gwapiv1.GatewayConditionProgrammed), metav1.ConditionTrue, string(gwapiv1.GatewayConditionProgrammed),
+			fmt.Sprintf(messageFmtProgrammed, deployment.Status.AvailableReplicas, deployment.Status.Replicas), time.Now(), gw.Generation))
 }
diff --git a/internal/infrastructure/kubernetes/infra_resource.go b/internal/infrastructure/kubernetes/infra_resource.go
index 01bf35c75..fc471f8af 100644
--- a/internal/infrastructure/kubernetes/infra_resource.go
+++ b/internal/infrastructure/kubernetes/infra_resource.go
@@ -31,20 +31,17 @@ func (i *Infra) createOrUpdateServiceAccount(ctx context.Context, r ResourceRend
 		}
 	)
 
-	resourceApplyTotal.With(labels...).Increment()
-
 	if sa, err = r.ServiceAccount(); err != nil {
-		resourceApplyFailed.With(labels...).Increment()
-
+		resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		return err
 	}
 
 	defer func() {
 		if err == nil {
 			resourceApplyDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceApplySuccess.With(labels...).Increment()
+			resourceApplyTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceApplyFailed.With(labels...).Increment()
+			resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -64,11 +61,8 @@ func (i *Infra) createOrUpdateConfigMap(ctx context.Context, r ResourceRender) (
 		}
 	)
 
-	resourceApplyTotal.With(labels...).Increment()
-
 	if cm, err = r.ConfigMap(); err != nil {
-		resourceApplyFailed.With(labels...).Increment()
-
+		resourceApplyTotal.WithFailure(metrics.StatusFailure, labels...).Increment()
 		return err
 	}
 
@@ -79,9 +73,9 @@ func (i *Infra) createOrUpdateConfigMap(ctx context.Context, r ResourceRender) (
 	defer func() {
 		if err == nil {
 			resourceApplyDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceApplySuccess.With(labels...).Increment()
+			resourceApplyTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceApplyFailed.With(labels...).Increment()
+			resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -101,11 +95,8 @@ func (i *Infra) createOrUpdateDeployment(ctx context.Context, r ResourceRender)
 		}
 	)
 
-	resourceApplyTotal.With(labels...).Increment()
-
 	if deployment, err = r.Deployment(); err != nil {
-		resourceApplyFailed.With(labels...).Increment()
-
+		resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		return err
 	}
 
@@ -119,9 +110,9 @@ func (i *Infra) createOrUpdateDeployment(ctx context.Context, r ResourceRender)
 	defer func() {
 		if err == nil {
 			resourceApplyDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceApplySuccess.With(labels...).Increment()
+			resourceApplyTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceApplyFailed.With(labels...).Increment()
+			resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -141,11 +132,8 @@ func (i *Infra) createOrUpdateDaemonSet(ctx context.Context, r ResourceRender) (
 		}
 	)
 
-	resourceApplyTotal.With(labels...).Increment()
-
 	if daemonSet, err = r.DaemonSet(); err != nil {
-		resourceApplyFailed.With(labels...).Increment()
-
+		resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		return err
 	}
 
@@ -159,9 +147,9 @@ func (i *Infra) createOrUpdateDaemonSet(ctx context.Context, r ResourceRender) (
 	defer func() {
 		if err == nil {
 			resourceApplyDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceApplySuccess.With(labels...).Increment()
+			resourceApplyTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceApplyFailed.With(labels...).Increment()
+			resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -179,10 +167,8 @@ func (i *Infra) createOrUpdatePodDisruptionBudget(ctx context.Context, r Resourc
 		}
 	)
 
-	resourceApplyTotal.With(labels...).Increment()
-
 	if pdb, err = r.PodDisruptionBudget(); err != nil {
-		resourceApplyFailed.With(labels...).Increment()
+		resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		return err
 	}
 
@@ -195,9 +181,9 @@ func (i *Infra) createOrUpdatePodDisruptionBudget(ctx context.Context, r Resourc
 	defer func() {
 		if err == nil {
 			resourceApplyDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceApplySuccess.With(labels...).Increment()
+			resourceApplyTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceApplyFailed.With(labels...).Increment()
+			resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -218,11 +204,8 @@ func (i *Infra) createOrUpdateHPA(ctx context.Context, r ResourceRender) (err er
 		}
 	)
 
-	resourceApplyTotal.With(labels...).Increment()
-
 	if hpa, err = r.HorizontalPodAutoscaler(); err != nil {
-		resourceApplyFailed.With(labels...).Increment()
-
+		resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		return err
 	}
 
@@ -235,9 +218,9 @@ func (i *Infra) createOrUpdateHPA(ctx context.Context, r ResourceRender) (err er
 	defer func() {
 		if err == nil {
 			resourceApplyDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceApplySuccess.With(labels...).Increment()
+			resourceApplyTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceApplyFailed.With(labels...).Increment()
+			resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -257,20 +240,17 @@ func (i *Infra) createOrUpdateService(ctx context.Context, r ResourceRender) (er
 		}
 	)
 
-	resourceApplyTotal.With(labels...).Increment()
-
 	if svc, err = r.Service(); err != nil {
-		resourceApplyFailed.With(labels...).Increment()
-
+		resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		return err
 	}
 
 	defer func() {
 		if err == nil {
 			resourceApplyDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceApplySuccess.With(labels...).Increment()
+			resourceApplyTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceApplyFailed.With(labels...).Increment()
+			resourceApplyTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -295,14 +275,12 @@ func (i *Infra) deleteServiceAccount(ctx context.Context, r ResourceRender) (err
 		}
 	)
 
-	resourceDeleteTotal.With(labels...).Increment()
-
 	defer func() {
 		if err == nil {
 			resourceDeleteDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceDeleteSuccess.With(labels...).Increment()
+			resourceDeleteTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceDeleteFailed.With(labels...).Increment()
+			resourceDeleteTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -327,14 +305,12 @@ func (i *Infra) deleteDeployment(ctx context.Context, r ResourceRender) (err err
 		}
 	)
 
-	resourceDeleteTotal.With(labels...).Increment()
-
 	defer func() {
 		if err == nil {
 			resourceDeleteDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceDeleteSuccess.With(labels...).Increment()
+			resourceDeleteTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceDeleteFailed.With(labels...).Increment()
+			resourceDeleteTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -359,14 +335,12 @@ func (i *Infra) deleteDaemonSet(ctx context.Context, r ResourceRender) (err erro
 		}
 	)
 
-	resourceDeleteTotal.With(labels...).Increment()
-
 	defer func() {
 		if err == nil {
 			resourceDeleteDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceDeleteSuccess.With(labels...).Increment()
+			resourceDeleteTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceDeleteFailed.With(labels...).Increment()
+			resourceDeleteTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -391,14 +365,12 @@ func (i *Infra) deleteConfigMap(ctx context.Context, r ResourceRender) (err erro
 		}
 	)
 
-	resourceDeleteTotal.With(labels...).Increment()
-
 	defer func() {
 		if err == nil {
 			resourceDeleteDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceDeleteSuccess.With(labels...).Increment()
+			resourceDeleteTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceDeleteFailed.With(labels...).Increment()
+			resourceDeleteTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -423,14 +395,12 @@ func (i *Infra) deleteService(ctx context.Context, r ResourceRender) (err error)
 		}
 	)
 
-	resourceDeleteTotal.With(labels...).Increment()
-
 	defer func() {
 		if err == nil {
 			resourceDeleteDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceDeleteSuccess.With(labels...).Increment()
+			resourceDeleteTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceDeleteFailed.With(labels...).Increment()
+			resourceDeleteTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -455,14 +425,12 @@ func (i *Infra) deleteHPA(ctx context.Context, r ResourceRender) (err error) {
 		}
 	)
 
-	resourceDeleteTotal.With(labels...).Increment()
-
 	defer func() {
 		if err == nil {
 			resourceDeleteDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceDeleteSuccess.With(labels...).Increment()
+			resourceDeleteTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceDeleteFailed.With(labels...).Increment()
+			resourceDeleteTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
@@ -487,14 +455,12 @@ func (i *Infra) deletePDB(ctx context.Context, r ResourceRender) (err error) {
 		}
 	)
 
-	resourceDeleteTotal.With(labels...).Increment()
-
 	defer func() {
 		if err == nil {
 			resourceDeleteDurationSeconds.With(labels...).Record(time.Since(startTime).Seconds())
-			resourceDeleteSuccess.With(labels...).Increment()
+			resourceDeleteTotal.WithSuccess(labels...).Increment()
 		} else {
-			resourceDeleteFailed.With(labels...).Increment()
+			resourceDeleteTotal.WithFailure(metrics.ReasonError, labels...).Increment()
 		}
 	}()
 
diff --git a/internal/infrastructure/kubernetes/metrics.go b/internal/infrastructure/kubernetes/metrics.go
index d417845b5..477a87e04 100644
--- a/internal/infrastructure/kubernetes/metrics.go
+++ b/internal/infrastructure/kubernetes/metrics.go
@@ -8,15 +8,27 @@ package kubernetes
 import "github.com/envoyproxy/gateway/internal/metrics"
 
 var (
-	resourceApplyTotal           = metrics.NewCounter("resource_apply_total", "Total number of applied resources.")
-	resourceApplyFailed          = metrics.NewCounter("resource_apply_failed", "Number of applied resources that failed.")
-	resourceApplySuccess         = metrics.NewCounter("resource_apply_success", "Number of applied resources that succeed.")
-	resourceApplyDurationSeconds = metrics.NewHistogram("resource_apply_duration_seconds", "How long in seconds a resource be applied successfully.", []float64{0.001, 0.01, 0.1, 1, 5, 10})
+	resourceApplyTotal = metrics.NewCounter(
+		"resource_apply_total",
+		"Total number of applied resources.",
+	)
 
-	resourceDeleteTotal           = metrics.NewCounter("resource_delete_total", "Total number of deleted resources.")
-	resourceDeleteFailed          = metrics.NewCounter("resource_delete_failed", "Number of deleted resources that failed.")
-	resourceDeleteSuccess         = metrics.NewCounter("resource_delete_success", "Number of deleted resources that succeed.")
-	resourceDeleteDurationSeconds = metrics.NewHistogram("resource_delete_duration_seconds", "How long in seconds a resource be deleted successfully.", []float64{0.001, 0.01, 0.1, 1, 5, 10})
+	resourceApplyDurationSeconds = metrics.NewHistogram(
+		"resource_apply_duration_seconds",
+		"How long in seconds a resource be applied successfully.",
+		[]float64{0.001, 0.01, 0.1, 1, 5, 10},
+	)
+
+	resourceDeleteTotal = metrics.NewCounter(
+		"resource_delete_total",
+		"Total number of deleted resources.",
+	)
+
+	resourceDeleteDurationSeconds = metrics.NewHistogram(
+		"resource_delete_duration_seconds",
+		"How long in seconds a resource be deleted successfully.",
+		[]float64{0.001, 0.01, 0.1, 1, 5, 10},
+	)
 
 	kindLabel      = metrics.NewLabel("kind")
 	nameLabel      = metrics.NewLabel("name")
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 42704cffe..8dc95e783 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -1795,9 +1795,10 @@ type Random struct{}
 // +k8s:deepcopy-gen=true
 type ConsistentHash struct {
 	// Hash based on the Source IP Address
-	SourceIP  *bool   `json:"sourceIP,omitempty" yaml:"sourceIP,omitempty"`
-	Header    *Header `json:"header,omitempty" yaml:"header,omitempty"`
-	TableSize *uint64 `json:"tableSize,omitempty" yaml:"tableSize,omitempty"`
+	SourceIP  *bool          `json:"sourceIP,omitempty" yaml:"sourceIP,omitempty"`
+	Header    *Header        `json:"header,omitempty" yaml:"header,omitempty"`
+	Cookie    *egv1a1.Cookie `json:"cookie,omitempty" yaml:"cookie,omitempty"`
+	TableSize *uint64        `json:"tableSize,omitempty" yaml:"tableSize,omitempty"`
 }
 
 // Header consistent hash type settings
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index 171c2c28d..d76ea363c 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -509,6 +509,11 @@ func (in *ConsistentHash) DeepCopyInto(out *ConsistentHash) {
 		*out = new(Header)
 		**out = **in
 	}
+	if in.Cookie != nil {
+		in, out := &in.Cookie, &out.Cookie
+		*out = new(v1alpha1.Cookie)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.TableSize != nil {
 		in, out := &in.TableSize, &out.TableSize
 		*out = new(uint64)
diff --git a/internal/message/metrics.go b/internal/message/metrics.go
index a78c9f87c..5f1201241 100644
--- a/internal/message/metrics.go
+++ b/internal/message/metrics.go
@@ -8,15 +8,22 @@ package message
 import "github.com/envoyproxy/gateway/internal/metrics"
 
 var (
-	watchableDepth = metrics.NewGauge("watchable_depth", "Current depth of watchable queue.")
-
-	watchableSubscribedDurationSeconds = metrics.NewHistogram("watchable_subscribed_duration_seconds", "How long in seconds a subscribed watchable is handled.", []float64{0.001, 0.01, 0.1, 1, 5, 10})
-
-	watchableSubscribedTotal = metrics.NewCounter("watchable_subscribed_total", "Total number of subscribed watchable.")
-
-	watchableSubscribedErrorsTotal = metrics.NewCounter("watchable_subscribed_errors_total", "Total number of subscribed watchable errors.")
-
-	runnerLabel = metrics.NewLabel("runner")
-
+	watchableDepth = metrics.NewGauge(
+		"watchable_depth",
+		"Current depth of watchable queue.",
+	)
+
+	watchableSubscribeDurationSeconds = metrics.NewHistogram(
+		"watchable_subscribe_duration_seconds",
+		"How long in seconds a subscribed watchable queue is handled.",
+		[]float64{0.001, 0.01, 0.1, 1, 5, 10},
+	)
+
+	watchableSubscribeTotal = metrics.NewCounter(
+		"watchable_subscribe_total",
+		"Total number of subscribed watchable queue.",
+	)
+
+	runnerLabel  = metrics.NewLabel("runner")
 	messageLabel = metrics.NewLabel("message")
 )
diff --git a/internal/message/watchutil.go b/internal/message/watchutil.go
index 2eb95725b..f8391cbc4 100644
--- a/internal/message/watchutil.go
+++ b/internal/message/watchutil.go
@@ -54,7 +54,7 @@ func HandleSubscription[K comparable, V any](
 	go func() {
 		for err := range errChans {
 			logger.WithValues("runner", meta.Runner).Error(err, "observed an error")
-			watchableSubscribedErrorsTotal.With(meta.LabelValues()...).Increment()
+			watchableSubscribeTotal.WithFailure(metrics.ReasonError, meta.LabelValues()...).Increment()
 		}
 	}()
 
@@ -65,8 +65,8 @@ func HandleSubscription[K comparable, V any](
 				Key:   k,
 				Value: v,
 			}, errChans)
-			watchableSubscribedTotal.With(meta.LabelValues()...).Increment()
-			watchableSubscribedDurationSeconds.With(meta.LabelValues()...).Record(time.Since(startHandleTime).Seconds())
+			watchableSubscribeTotal.WithSuccess(meta.LabelValues()...).Increment()
+			watchableSubscribeDurationSeconds.With(meta.LabelValues()...).Record(time.Since(startHandleTime).Seconds())
 		}
 	}
 	for snapshot := range subscription {
@@ -74,8 +74,8 @@ func HandleSubscription[K comparable, V any](
 		for _, update := range snapshot.Updates {
 			startHandleTime := time.Now()
 			handle(Update[K, V](update), errChans)
-			watchableSubscribedTotal.With(meta.LabelValues()...).Increment()
-			watchableSubscribedDurationSeconds.With(meta.LabelValues()...).Record(time.Since(startHandleTime).Seconds())
+			watchableSubscribeTotal.WithSuccess(meta.LabelValues()...).Increment()
+			watchableSubscribeDurationSeconds.With(meta.LabelValues()...).Record(time.Since(startHandleTime).Seconds())
 		}
 	}
 }
diff --git a/internal/metrics/otel_label.go b/internal/metrics/otel_label.go
index 45d04ff4b..bcf4c4722 100644
--- a/internal/metrics/otel_label.go
+++ b/internal/metrics/otel_label.go
@@ -7,6 +7,24 @@ package metrics
 
 import "go.opentelemetry.io/otel/attribute"
 
+var (
+	// statusLabel defines a label to indicate the status of current metric,
+	// e.g. is a SUCCESS or FAILURE status.
+	statusLabel = NewLabel("status")
+
+	// reasonLabel defines a label to indicate the reason of failure status metric,
+	// it's an optional label.
+	reasonLabel = NewLabel("reason")
+)
+
+const (
+	StatusSuccess = "success"
+	StatusFailure = "failure"
+
+	ReasonError    = "error"
+	ReasonConflict = "conflict"
+)
+
 // A Label provides a named dimension for a Metric.
 type Label struct {
 	key attribute.Key
diff --git a/internal/metrics/otel_metric_counter.go b/internal/metrics/otel_metric_counter.go
index 93dcaa136..5cf194dec 100644
--- a/internal/metrics/otel_metric_counter.go
+++ b/internal/metrics/otel_metric_counter.go
@@ -46,3 +46,26 @@ func (f *Counter) With(labelValues ...LabelValue) *Counter {
 
 	return m
 }
+
+func (f *Counter) WithStatus(status string, labelValues ...LabelValue) *Counter {
+	labelValues = append(labelValues, statusLabel.Value(status))
+	return f.With(labelValues...)
+}
+
+func (f *Counter) WithSuccess(labelValues ...LabelValue) *Counter {
+	if len(labelValues) > 0 {
+		labelValues = append(labelValues, statusLabel.Value(StatusSuccess))
+	} else {
+		labelValues = []LabelValue{statusLabel.Value(StatusSuccess)}
+	}
+	return f.With(labelValues...)
+}
+
+func (f *Counter) WithFailure(reason string, labelValues ...LabelValue) *Counter {
+	if len(labelValues) > 0 {
+		labelValues = append(labelValues, statusLabel.Value(StatusFailure), reasonLabel.Value(reason))
+	} else {
+		labelValues = []LabelValue{statusLabel.Value(StatusFailure), reasonLabel.Value(reason)}
+	}
+	return f.With(labelValues...)
+}
diff --git a/internal/provider/kubernetes/metrics.go b/internal/provider/kubernetes/metrics.go
index 236aa150e..ba617e208 100644
--- a/internal/provider/kubernetes/metrics.go
+++ b/internal/provider/kubernetes/metrics.go
@@ -8,12 +8,21 @@ package kubernetes
 import "github.com/envoyproxy/gateway/internal/metrics"
 
 var (
-	statusUpdateTotal           = metrics.NewCounter("status_update_total", "Total number of status updates by object kind.")
-	statusUpdateFailed          = metrics.NewCounter("status_update_failed_total", "Number of status updates that failed by object kind.")
-	statusUpdateConflict        = metrics.NewCounter("status_update_conflict_total", "Number of status update conflicts encountered by object kind.")
-	statusUpdateSuccess         = metrics.NewCounter("status_update_success_total", "Number of status updates that succeeded by object kind.")
-	statusUpdateNoop            = metrics.NewCounter("status_update_noop_total", "Number of status updates that are no-ops by object kind. This is a subset of successful status updates.")
-	statusUpdateDurationSeconds = metrics.NewHistogram("status_update_duration_seconds", "How long a status update takes to finish.", []float64{0.001, 0.01, 0.1, 1, 5, 10})
+	statusUpdateTotal = metrics.NewCounter(
+		"status_update_total",
+		"Total number of status update by object kind.",
+	)
+
+	statusUpdateDurationSeconds = metrics.NewHistogram(
+		"status_update_duration_seconds",
+		"How long a status update takes to finish.",
+		[]float64{0.001, 0.01, 0.1, 1, 5, 10},
+	)
 
 	kindLabel = metrics.NewLabel("kind")
 )
+
+const (
+	// statusNoAction means the status of metric is taking no action.
+	statusNoAction = "NoAction"
+)
diff --git a/internal/provider/kubernetes/status_updater.go b/internal/provider/kubernetes/status_updater.go
index c6bc5d7f1..59ff64d33 100644
--- a/internal/provider/kubernetes/status_updater.go
+++ b/internal/provider/kubernetes/status_updater.go
@@ -24,6 +24,7 @@ import (
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 	"github.com/envoyproxy/gateway/internal/gatewayapi"
+	"github.com/envoyproxy/gateway/internal/metrics"
 )
 
 // Update contains an all the information needed to update an object's status.
@@ -75,8 +76,6 @@ func (u *UpdateHandler) apply(update Update) {
 		objKind   = kindOf(obj)
 	)
 
-	statusUpdateTotal.With(kindLabel.Value(objKind)).Increment()
-
 	defer func() {
 		updateDuration := time.Since(startTime)
 		statusUpdateDurationSeconds.With(kindLabel.Value(objKind)).Record(updateDuration.Seconds())
@@ -84,7 +83,7 @@ func (u *UpdateHandler) apply(update Update) {
 
 	if err := retry.OnError(retry.DefaultBackoff, func(err error) bool {
 		if kerrors.IsConflict(err) {
-			statusUpdateConflict.With(kindLabel.Value(objKind)).Increment()
+			statusUpdateTotal.WithFailure(metrics.ReasonConflict, kindLabel.Value(objKind)).Increment()
 			return true
 		}
 		return false
@@ -104,7 +103,7 @@ func (u *UpdateHandler) apply(update Update) {
 				WithName(update.NamespacedName.Namespace).
 				Info("status unchanged, bypassing update")
 
-			statusUpdateNoop.With(kindLabel.Value(objKind)).Increment()
+			statusUpdateTotal.WithStatus(statusNoAction, kindLabel.Value(objKind)).Increment()
 			return nil
 		}
 
@@ -115,9 +114,9 @@ func (u *UpdateHandler) apply(update Update) {
 		u.log.Error(err, "unable to update status", "name", update.NamespacedName.Name,
 			"namespace", update.NamespacedName.Namespace)
 
-		statusUpdateFailed.With(kindLabel.Value(objKind)).Increment()
+		statusUpdateTotal.WithFailure(metrics.ReasonError, kindLabel.Value(objKind)).Increment()
 	} else {
-		statusUpdateSuccess.With(kindLabel.Value(objKind)).Increment()
+		statusUpdateTotal.WithSuccess(kindLabel.Value(objKind)).Increment()
 	}
 }
 
diff --git a/internal/wasm/cache.go b/internal/wasm/cache.go
index 8bd94508b..6082a0788 100644
--- a/internal/wasm/cache.go
+++ b/internal/wasm/cache.go
@@ -239,7 +239,7 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry,
 		// Download the Wasm module with http fetcher.
 		b, err = c.httpFetcher.Fetch(ctx, key.downloadURL, insecure)
 		if err != nil {
-			wasmRemoteFetchCount.With(resultTag.Value(downloadFailure)).Increment()
+			wasmRemoteFetchTotal.WithFailure(reasonDownloadError).Increment()
 			return nil, err
 		}
 
@@ -251,7 +251,7 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry,
 			isPrivate = true
 		}
 		if imageBinaryFetcher, dChecksum, err = c.prepareFetch(ctx, u, insecure, opts); err != nil {
-			wasmRemoteFetchCount.With(resultTag.Value(manifestFailure)).Increment()
+			wasmRemoteFetchTotal.WithFailure(reasonManifestError).Increment()
 			return nil, fmt.Errorf("could not fetch Wasm OCI image: %w", err)
 		}
 	default:
@@ -261,7 +261,7 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry,
 	// If the checksum is provided, check if it matches the downloaded binary.
 	if key.checksum != "" {
 		if dChecksum != key.checksum {
-			wasmRemoteFetchCount.With(resultTag.Value(checksumMismatch)).Increment()
+			wasmRemoteFetchTotal.WithFailure(reasonChecksumMismatch).Increment()
 			return nil, fmt.Errorf("module downloaded from %v has checksum %v, which does not match: %v", key.downloadURL, dChecksum, key.checksum)
 		}
 	} else {
@@ -272,17 +272,18 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry,
 	if imageBinaryFetcher != nil {
 		b, err = imageBinaryFetcher()
 		if err != nil {
-			wasmRemoteFetchCount.With(resultTag.Value(downloadFailure)).Increment()
+			wasmRemoteFetchTotal.WithFailure(reasonDownloadError).Increment()
 			return nil, fmt.Errorf("could not fetch Wasm binary: %w", err)
 		}
 	}
 
 	if !isValidWasmBinary(b) {
-		wasmRemoteFetchCount.With(resultTag.Value(fetchFailure)).Increment()
+		wasmRemoteFetchTotal.WithFailure(reasonFetchError).Increment()
 		return nil, fmt.Errorf("fetched Wasm binary from %s is invalid", key.downloadURL)
 	}
 
-	wasmRemoteFetchCount.With(resultTag.Value(fetchSuccess)).Increment()
+	wasmRemoteFetchTotal.WithSuccess().Increment()
+
 	return c.addEntry(key, b, isPrivate)
 }
 
@@ -365,7 +366,9 @@ func (c *localFileCache) addEntry(key cacheKey, wasmModule []byte, isPrivate boo
 	}
 	ce.referencingURLs.Insert(key.downloadURL)
 	c.modules[key.moduleKey] = &ce
+
 	wasmCacheEntries.Record(float64(len(c.modules)))
+
 	return &ce, nil
 }
 
@@ -378,7 +381,7 @@ func (c *localFileCache) getEntry(key cacheKey, pullPolicy PullPolicy, u *url.UR
 	c.mux.Lock()
 	defer func() {
 		c.mux.Unlock()
-		wasmCacheLookupCount.With(hitTag.Value(strconv.FormatBool(cacheHit))).Increment()
+		wasmCacheLookupTotal.With(hitTag.Value(strconv.FormatBool(cacheHit))).Increment()
 	}()
 
 	// If no checksum is provided, check if a wasm module with the same downloading URL has been pulled before.
diff --git a/internal/wasm/metrics.go b/internal/wasm/metrics.go
index 9de7e6208..01cd43645 100644
--- a/internal/wasm/metrics.go
+++ b/internal/wasm/metrics.go
@@ -21,33 +21,29 @@ package wasm
 
 import "github.com/envoyproxy/gateway/internal/metrics"
 
-// Const strings for label value.
 const (
-	// For remote fetch metric.
-	fetchSuccess     = "success"
-	fetchFailure     = "fetch_failure"
-	downloadFailure  = "download_failure"
-	manifestFailure  = "manifest_failure"
-	checksumMismatch = "checksum_mismatched"
+	reasonFetchError       = "fetch_error"
+	reasonDownloadError    = "download_error"
+	reasonManifestError    = "manifest_error"
+	reasonChecksumMismatch = "checksum_mismatched"
 )
 
 var (
-	hitTag    = metrics.NewLabel("hit")
-	resultTag = metrics.NewLabel("result")
+	hitTag = metrics.NewLabel("hit")
 
 	wasmCacheEntries = metrics.NewGauge(
 		"wasm_cache_entries",
-		"number of Wasm remote fetch cache entries.",
+		"Number of Wasm remote fetch cache entries.",
 	)
 
-	wasmCacheLookupCount = metrics.NewCounter(
-		"wasm_cache_lookup_count",
-		"number of Wasm remote fetch cache lookups.",
+	wasmCacheLookupTotal = metrics.NewCounter(
+		"wasm_cache_lookup_total",
+		"Total number of Wasm remote fetch cache lookups.",
 	)
 
-	wasmRemoteFetchCount = metrics.NewCounter(
-		"wasm_remote_fetch_count",
-		"number of Wasm remote fetches and results, including success, download failure, and checksum mismatch.",
+	wasmRemoteFetchTotal = metrics.NewCounter(
+		"wasm_remote_fetch_total",
+		"Total number of Wasm remote fetches and results.",
 	)
 )
 
diff --git a/internal/xds/cache/metrics.go b/internal/xds/cache/metrics.go
index 3480b9c40..f5787e996 100644
--- a/internal/xds/cache/metrics.go
+++ b/internal/xds/cache/metrics.go
@@ -8,16 +8,23 @@ package cache
 import "github.com/envoyproxy/gateway/internal/metrics"
 
 var (
-	xdsSnapshotCreationTotal   = metrics.NewCounter("xds_snapshot_creation_total", "Total number of xds snapshot cache creation.")
-	xdsSnapshotCreationFailed  = metrics.NewCounter("xds_snapshot_creation_failed", "Number of xds snapshot cache creation that failed.")
-	xdsSnapshotCreationSuccess = metrics.NewCounter("xds_snapshot_creation_success", "Number of xds snapshot cache creation that succeeded.")
+	xdsSnapshotCreateTotal = metrics.NewCounter(
+		"xds_snapshot_create_total",
+		"Total number of xds snapshot cache creates.",
+	)
 
-	xdsSnapshotUpdateTotal   = metrics.NewCounter("xds_snapshot_update_total", "Total number of xds snapshot cache updates by node id.")
-	xdsSnapshotUpdateFailed  = metrics.NewCounter("xds_snapshot_update_failed", "Number of xds snapshot cache updates that failed by node id.")
-	xdsSnapshotUpdateSuccess = metrics.NewCounter("xds_snapshot_update_success", "Number of xds snapshot cache updates that succeeded by node id.")
-	nodeIDLabel              = metrics.NewLabel("nodeID")
+	xdsSnapshotUpdateTotal = metrics.NewCounter(
+		"xds_snapshot_update_total",
+		"Total number of xds snapshot cache updates by node id.",
+	)
 
-	xdsStreamDurationSeconds      = metrics.NewHistogram("xds_stream_duration_seconds", "How long a xds stream takes to finish.", []float64{0.1, 10, 50, 100, 1000, 10000})
-	xdsDeltaStreamDurationSeconds = metrics.NewHistogram("xds_delta_stream_duration_seconds", "How long a xds delta stream takes to finish.", []float64{0.1, 10, 50, 100, 1000, 10000})
-	streamIDLabel                 = metrics.NewLabel("streamID")
+	xdsStreamDurationSeconds = metrics.NewHistogram(
+		"xds_stream_duration_seconds",
+		"How long a xds stream takes to finish.",
+		[]float64{0.1, 10, 50, 100, 1000, 10000},
+	)
+
+	nodeIDLabel        = metrics.NewLabel("nodeID")
+	streamIDLabel      = metrics.NewLabel("streamID")
+	isDeltaStreamLabel = metrics.NewLabel("isDeltaStream")
 )
diff --git a/internal/xds/cache/snapshotcache.go b/internal/xds/cache/snapshotcache.go
index 383aad836..633021aa1 100644
--- a/internal/xds/cache/snapshotcache.go
+++ b/internal/xds/cache/snapshotcache.go
@@ -28,6 +28,7 @@ import (
 	"go.uber.org/zap"
 
 	"github.com/envoyproxy/gateway/internal/logging"
+	"github.com/envoyproxy/gateway/internal/metrics"
 	"github.com/envoyproxy/gateway/internal/xds/types"
 )
 
@@ -78,26 +79,22 @@ func (s *snapshotCache) GenerateNewSnapshot(irKey string, resources types.XdsRes
 		version,
 		resources,
 	)
-
-	xdsSnapshotCreationTotal.Increment()
 	if err != nil {
-		xdsSnapshotCreationFailed.Increment()
+		xdsSnapshotCreateTotal.WithFailure(metrics.ReasonError).Increment()
 		return err
-	} else {
-		xdsSnapshotCreationSuccess.Increment()
 	}
+	xdsSnapshotCreateTotal.WithSuccess().Increment()
 
 	s.lastSnapshot[irKey] = snapshot
 
 	for _, node := range s.getNodeIDs(irKey) {
 		s.log.Debugf("Generating a snapshot with Node %s", node)
-		xdsSnapshotUpdateTotal.With(nodeIDLabel.Value(node)).Increment()
 
 		if err = s.SetSnapshot(context.TODO(), node, snapshot); err != nil {
-			xdsSnapshotUpdateFailed.With(nodeIDLabel.Value(node)).Increment()
+			xdsSnapshotUpdateTotal.WithFailure(metrics.ReasonError, nodeIDLabel.Value(node)).Increment()
 			return err
 		} else {
-			xdsSnapshotUpdateSuccess.With(nodeIDLabel.Value(node)).Increment()
+			xdsSnapshotUpdateTotal.WithSuccess(nodeIDLabel.Value(node)).Increment()
 		}
 	}
 
@@ -168,6 +165,7 @@ func (s *snapshotCache) OnStreamClosed(streamID int64, node *corev3.Node) {
 		xdsStreamDurationSeconds.With(
 			streamIDLabel.Value(strconv.FormatInt(streamID, 10)),
 			nodeIDLabel.Value(node.Id),
+			isDeltaStreamLabel.Value("false"),
 		).Record(streamDuration.Seconds())
 	}
 
@@ -267,9 +265,10 @@ func (s *snapshotCache) OnDeltaStreamClosed(streamID int64, node *corev3.Node) {
 
 	if startTime, ok := s.deltaStreamDuration[streamID]; ok {
 		deltaStreamDuration := time.Since(startTime)
-		xdsDeltaStreamDurationSeconds.With(
+		xdsStreamDurationSeconds.With(
 			streamIDLabel.Value(strconv.FormatInt(streamID, 10)),
 			nodeIDLabel.Value(node.Id),
+			isDeltaStreamLabel.Value("true"),
 		).Record(deltaStreamDuration.Seconds())
 	}
 
diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go
index ba1baa6c2..139b359a1 100644
--- a/internal/xds/translator/route.go
+++ b/internal/xds/translator/route.go
@@ -493,6 +493,28 @@ func buildHashPolicy(httpRoute *ir.HTTPRoute) []*routev3.RouteAction_HashPolicy
 			},
 		}
 		return []*routev3.RouteAction_HashPolicy{hashPolicy}
+	case ch.Cookie != nil:
+		hashPolicy := &routev3.RouteAction_HashPolicy{
+			PolicySpecifier: &routev3.RouteAction_HashPolicy_Cookie_{
+				Cookie: &routev3.RouteAction_HashPolicy_Cookie{
+					Name: ch.Cookie.Name,
+				},
+			},
+		}
+		if ch.Cookie.TTL != nil {
+			hashPolicy.GetCookie().Ttl = durationpb.New(ch.Cookie.TTL.Duration)
+		}
+		if ch.Cookie.Attributes != nil {
+			attributes := make([]*routev3.RouteAction_HashPolicy_CookieAttribute, len(ch.Cookie.Attributes))
+			i := 0
+			for name, value := range ch.Cookie.Attributes {
+				attributes[i].Name = name
+				attributes[i].Value = value
+				i++
+			}
+			hashPolicy.GetCookie().Attributes = attributes
+		}
+		return []*routev3.RouteAction_HashPolicy{hashPolicy}
 	case ch.SourceIP != nil:
 		if !*ch.SourceIP {
 			return nil
diff --git a/site/content/en/contributions/DEVELOP.md b/site/content/en/contributions/DEVELOP.md
index c9c4cbb24..555bf3296 100644
--- a/site/content/en/contributions/DEVELOP.md
+++ b/site/content/en/contributions/DEVELOP.md
@@ -145,6 +145,34 @@ verify signature was copied to [JWK Creator][] for generating the JWK. The JWK C
 settings, i.e. `Signing` public key use and the `RS256` algorithm. The generated JWK was wrapped in a JWKS structure
 and is hosted in the repo.
 
+### Benchmarking
+
+Envoy Gateway uses [nighthawk][nighthawk] for benchmarking, and mainly concerned with
+its performance and scalability as a control-plane.
+
+The performance and scalability concerns come from several aspects for control-plane:
+
+- The consumption of memory and CPU.
+- The rate of configuration changes.
+
+The benchmark test is running on [Kind][Kind] cluster, you can run the following command
+to start a Kind cluster and run benchmark test on it.
+
+```shell
+make benchmark-test
+```
+
+By default, a benchmark report will be generated under `test/benchmark` after test finished.
+
+#### Brief benchmark report
+
+You can browse the detailed benchmark report in `test/benchmark/benchmark-report.md`.
+
+Here are some brief benchmark reports about Envoy Gateway: 
+
+- It will take up nearly 1.3GiB memory and 11s total CPU time for (1 GatewayClass + 1 Gateway + 500 HTTRoutes) settings
+
+
 [Quickstart]: https://github.com/envoyproxy/gateway/blob/main/docs/latest/user/quickstart.md
 [make]: https://www.gnu.org/software/make/
 [Github Actions]: https://docs.github.com/en/actions
@@ -161,3 +189,4 @@ and is hosted in the repo.
 [request authentication]: ../latest/tasks/security/jwt-authentication
 [JWT Debugger]: https://jwt.io/
 [JWK Creator]: https://russelldavies.github.io/jwk-creator/
+[nighthawk]: https://github.com/envoyproxy/nighthawk
diff --git a/tools/make/lint.mk b/tools/make/lint.mk
index 74a161b58..10a7dbd02 100644
--- a/tools/make/lint.mk
+++ b/tools/make/lint.mk
@@ -5,6 +5,7 @@
 ##@ Lint
 
 GITHUB_ACTION ?=
+LINT_BUILD_TAGS ?= e2e,celvalidation,conformance,experimental,benchmark
 
 .PHONY: lint
 lint: ## Run all linter of code sources, including golint, yamllint, whitenoise lint and codespell.
@@ -20,7 +21,7 @@ lint: lint.golint
 lint-deps: $(tools/golangci-lint)
 lint.golint: $(tools/golangci-lint)
 	@$(LOG_TARGET)
-	$(tools/golangci-lint) run $(GOLANGCI_LINT_FLAGS) --build-tags=e2e,celvalidation,conformance,experimental --config=tools/linter/golangci-lint/.golangci.yml
+	$(tools/golangci-lint) run $(GOLANGCI_LINT_FLAGS) --build-tags=$(LINT_BUILD_TAGS) --config=tools/linter/golangci-lint/.golangci.yml
 
 .PHONY: lint.yamllint
 lint: lint.yamllint


Test patch:
diff --git a/internal/gatewayapi/helpers_test.go b/internal/gatewayapi/helpers_test.go
index 5f61a1cc1..0339141de 100644
--- a/internal/gatewayapi/helpers_test.go
+++ b/internal/gatewayapi/helpers_test.go
@@ -15,8 +15,13 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/require"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/utils/ptr"
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
+	gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
+
+	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 )
 
 func TestValidateGRPCFilterRef(t *testing.T) {
@@ -194,3 +199,289 @@ func TestValidateHTTPFilterRef(t *testing.T) {
 		})
 	}
 }
+
+func TestGetPolicyTargetRefs(t *testing.T) {
+	testCases := []struct {
+		name    string
+		policy  egv1a1.PolicyTargetReferences
+		targets []*unstructured.Unstructured
+		results []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName
+	}{
+		{
+			name: "simple",
+			policy: egv1a1.PolicyTargetReferences{
+				TargetSelectors: []egv1a1.TargetSelector{
+					{
+						Kind:  "Gateway",
+						Group: ptr.To(gwapiv1.Group("gateway.networking.k8s.io")),
+						MatchLabels: map[string]string{
+							"pick": "me",
+						},
+					},
+				},
+			},
+			targets: []*unstructured.Unstructured{
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "first",
+							"namespace": "default",
+							"labels": map[string]any{
+								"some": "random label",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "second",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "TLSRoute",
+						"metadata": map[string]any{
+							"name":      "third",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+			},
+			results: []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+				{
+					LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+						Group: "gateway.networking.k8s.io",
+						Kind:  "Gateway",
+						Name:  "second",
+					},
+				},
+			},
+		},
+		{
+			name: "multiple selectors",
+			policy: egv1a1.PolicyTargetReferences{
+				TargetSelectors: []egv1a1.TargetSelector{
+					{
+						Kind: "TLSRoute",
+						MatchLabels: map[string]string{
+							"pick": "me",
+						},
+					},
+					{
+						Kind: "Gateway",
+						MatchLabels: map[string]string{
+							"pick": "me",
+						},
+					},
+				},
+			},
+			targets: []*unstructured.Unstructured{
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "first",
+							"namespace": "default",
+							"labels": map[string]any{
+								"some": "random label",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "second",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "TLSRoute",
+						"metadata": map[string]any{
+							"name":      "third",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+			},
+			results: []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+				{
+					LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+						Group: "gateway.networking.k8s.io",
+						Kind:  "TLSRoute",
+						Name:  "third",
+					},
+				},
+				{
+					LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+						Group: "gateway.networking.k8s.io",
+						Kind:  "Gateway",
+						Name:  "second",
+					},
+				},
+			},
+		},
+		{
+			name: "deduplicated",
+			policy: egv1a1.PolicyTargetReferences{
+				TargetRefs: []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+					{
+						LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+							Group: "gateway.networking.k8s.io",
+							Kind:  "TLSRoute",
+							Name:  "third",
+						},
+					},
+				},
+				TargetSelectors: []egv1a1.TargetSelector{
+					{
+						Kind: "TLSRoute",
+						MatchLabels: map[string]string{
+							"pick": "me",
+						},
+					},
+				},
+			},
+			targets: []*unstructured.Unstructured{
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "first",
+							"namespace": "default",
+							"labels": map[string]any{
+								"some": "random label",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "second",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "TLSRoute",
+						"metadata": map[string]any{
+							"name":      "third",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+			},
+			results: []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+				{
+					LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+						Group: "gateway.networking.k8s.io",
+						Kind:  "TLSRoute",
+						Name:  "third",
+					},
+				},
+			},
+		},
+		{
+			name: "bad-group-is-ignored",
+			policy: egv1a1.PolicyTargetReferences{
+				TargetSelectors: []egv1a1.TargetSelector{
+					{
+						Kind:  "Gateway",
+						Group: ptr.To(gwapiv1.Group("bad-group")),
+						MatchLabels: map[string]string{
+							"pick": "me",
+						},
+					},
+				},
+			},
+			targets: []*unstructured.Unstructured{
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "first",
+							"namespace": "default",
+							"labels": map[string]any{
+								"some": "random label",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "Gateway",
+						"metadata": map[string]any{
+							"name":      "second",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+				{
+					Object: map[string]any{
+						"apiVersion": "gateway.networking.k8s.io/v1",
+						"kind":       "TLSRoute",
+						"metadata": map[string]any{
+							"name":      "third",
+							"namespace": "default",
+							"labels": map[string]any{
+								"pick": "me",
+							},
+						},
+					},
+				},
+			},
+			results: []gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			results := getPolicyTargetRefs(tc.policy, tc.targets)
+			require.ElementsMatch(t, results, tc.results)
+		})
+	}
+}
diff --git a/internal/gatewayapi/status/gateway_test.go b/internal/gatewayapi/status/gateway_test.go
index 55524349d..0be99b7d4 100644
--- a/internal/gatewayapi/status/gateway_test.go
+++ b/internal/gatewayapi/status/gateway_test.go
@@ -6,9 +6,13 @@
 package status
 
 import (
+	"fmt"
 	"reflect"
+	"strconv"
 	"testing"
 
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
 	"github.com/stretchr/testify/assert"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
@@ -17,24 +21,26 @@ import (
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
 )
 
+// TestUpdateGatewayStatusProgrammedCondition tests whether UpdateGatewayStatusProgrammedCondition correctly updates the addresses in the Gateway status.
 func TestUpdateGatewayStatusProgrammedCondition(t *testing.T) {
 	type args struct {
-		gw         *gwapiv1.Gateway
-		svc        *corev1.Service
-		deployment *appsv1.Deployment
-		addresses  []gwapiv1.GatewayStatusAddress
+		gw            *gwapiv1.Gateway
+		svc           *corev1.Service
+		deployment    *appsv1.Deployment
+		nodeAddresses []string
 	}
 	tests := []struct {
-		name string
-		args args
+		name          string
+		args          args
+		wantAddresses []gwapiv1.GatewayStatusAddress
 	}{
 		{
 			name: "nil svc",
 			args: args{
-				gw:        &gwapiv1.Gateway{},
-				svc:       nil,
-				addresses: nil,
+				gw:  &gwapiv1.Gateway{},
+				svc: nil,
 			},
+			wantAddresses: nil,
 		},
 		{
 			name: "LoadBalancer svc with ingress ip",
@@ -57,11 +63,11 @@ func TestUpdateGatewayStatusProgrammedCondition(t *testing.T) {
 						},
 					},
 				},
-				addresses: []gwapiv1.GatewayStatusAddress{
-					{
-						Type:  ptr.To(gwapiv1.IPAddressType),
-						Value: "127.0.0.1",
-					},
+			},
+			wantAddresses: []gwapiv1.GatewayStatusAddress{
+				{
+					Type:  ptr.To(gwapiv1.IPAddressType),
+					Value: "127.0.0.1",
 				},
 			},
 		},
@@ -86,15 +92,15 @@ func TestUpdateGatewayStatusProgrammedCondition(t *testing.T) {
 						},
 					},
 				},
-				addresses: []gwapiv1.GatewayStatusAddress{
-					{
-						Type:  ptr.To(gwapiv1.IPAddressType),
-						Value: "127.0.0.1",
-					},
-					{
-						Type:  ptr.To(gwapiv1.HostnameAddressType),
-						Value: "localhost",
-					},
+			},
+			wantAddresses: []gwapiv1.GatewayStatusAddress{
+				{
+					Type:  ptr.To(gwapiv1.IPAddressType),
+					Value: "127.0.0.1",
+				},
+				{
+					Type:  ptr.To(gwapiv1.HostnameAddressType),
+					Value: "localhost",
 				},
 			},
 		},
@@ -110,55 +116,135 @@ func TestUpdateGatewayStatusProgrammedCondition(t *testing.T) {
 						Type:       corev1.ServiceTypeClusterIP,
 					},
 				},
-				addresses: []gwapiv1.GatewayStatusAddress{
-					{
-						Type:  ptr.To(gwapiv1.IPAddressType),
-						Value: "127.0.0.1",
+			},
+			wantAddresses: []gwapiv1.GatewayStatusAddress{
+				{
+					Type:  ptr.To(gwapiv1.IPAddressType),
+					Value: "127.0.0.1",
+				},
+			},
+		},
+		{
+			name: "Nodeport svc",
+			args: args{
+				gw:            &gwapiv1.Gateway{},
+				nodeAddresses: []string{"1", "2"},
+				svc: &corev1.Service{
+					TypeMeta:   metav1.TypeMeta{},
+					ObjectMeta: metav1.ObjectMeta{},
+					Spec: corev1.ServiceSpec{
+						Type: corev1.ServiceTypeNodePort,
 					},
 				},
 			},
+			wantAddresses: []gwapiv1.GatewayStatusAddress{
+				{
+					Type:  ptr.To(gwapiv1.IPAddressType),
+					Value: "1",
+				},
+				{
+					Type:  ptr.To(gwapiv1.IPAddressType),
+					Value: "2",
+				},
+			},
+		},
+		{
+			name: "Nodeport svc with too many node addresses",
+			args: args{
+				gw: &gwapiv1.Gateway{},
+				// 20 node addresses
+				nodeAddresses: func() (addr []string) {
+					for i := 0; i < 20; i++ {
+						addr = append(addr, strconv.Itoa(i))
+					}
+					return
+				}(),
+				svc: &corev1.Service{
+					TypeMeta:   metav1.TypeMeta{},
+					ObjectMeta: metav1.ObjectMeta{},
+					Spec: corev1.ServiceSpec{
+						Type: corev1.ServiceTypeNodePort,
+					},
+				},
+			},
+			// Only the first 16 addresses should be set.
+			wantAddresses: func() (addr []gwapiv1.GatewayStatusAddress) {
+				for i := 0; i < 16; i++ {
+					addr = append(addr, gwapiv1.GatewayStatusAddress{
+						Type:  ptr.To(gwapiv1.IPAddressType),
+						Value: strconv.Itoa(i),
+					})
+				}
+				return
+			}(),
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			UpdateGatewayStatusProgrammedCondition(tt.args.gw, tt.args.svc, tt.args.deployment)
-			assert.True(t, reflect.DeepEqual(tt.args.addresses, tt.args.gw.Status.Addresses))
+			UpdateGatewayStatusProgrammedCondition(tt.args.gw, tt.args.svc, tt.args.deployment, tt.args.nodeAddresses...)
+			assert.True(t, reflect.DeepEqual(tt.wantAddresses, tt.args.gw.Status.Addresses))
 		})
 	}
 }
 
-func TestGatewayReadyCondition(t *testing.T) {
+func TestUpdateGatewayProgrammedCondition(t *testing.T) {
 	testCases := []struct {
-		name             string
-		serviceAddress   bool
-		deploymentStatus appsv1.DeploymentStatus
-		expect           metav1.Condition
+		name string
+		// serviceAddressNum indicates how many addresses are set in the Gateway status.
+		serviceAddressNum int
+		deploymentStatus  appsv1.DeploymentStatus
+		expectCondition   []metav1.Condition
 	}{
 		{
-			name:             "ready gateway",
-			serviceAddress:   true,
-			deploymentStatus: appsv1.DeploymentStatus{AvailableReplicas: 1},
-			expect: metav1.Condition{
-				Status: metav1.ConditionTrue,
-				Reason: string(gwapiv1.GatewayConditionProgrammed),
+			name:              "ready gateway",
+			serviceAddressNum: 1,
+			deploymentStatus:  appsv1.DeploymentStatus{AvailableReplicas: 1, Replicas: 1},
+			expectCondition: []metav1.Condition{
+				{
+					Type:    string(gwapiv1.GatewayConditionProgrammed),
+					Status:  metav1.ConditionTrue,
+					Reason:  string(gwapiv1.GatewayConditionProgrammed),
+					Message: fmt.Sprintf(messageFmtProgrammed, 1, 1),
+				},
 			},
 		},
 		{
-			name:             "not ready gateway without address",
-			serviceAddress:   false,
-			deploymentStatus: appsv1.DeploymentStatus{AvailableReplicas: 1},
-			expect: metav1.Condition{
-				Status: metav1.ConditionFalse,
-				Reason: string(gwapiv1.GatewayReasonAddressNotAssigned),
+			name:              "not ready gateway without address",
+			serviceAddressNum: 0,
+			deploymentStatus:  appsv1.DeploymentStatus{AvailableReplicas: 1},
+			expectCondition: []metav1.Condition{
+				{
+					Type:    string(gwapiv1.GatewayConditionProgrammed),
+					Status:  metav1.ConditionFalse,
+					Reason:  string(gwapiv1.GatewayReasonAddressNotAssigned),
+					Message: messageAddressNotAssigned,
+				},
 			},
 		},
 		{
-			name:             "not ready gateway with address unavailable pods",
-			serviceAddress:   true,
-			deploymentStatus: appsv1.DeploymentStatus{AvailableReplicas: 0},
-			expect: metav1.Condition{
-				Status: metav1.ConditionFalse,
-				Reason: string(gwapiv1.GatewayReasonNoResources),
+			name:              "not ready gateway with too many addresses",
+			serviceAddressNum: 17,
+			deploymentStatus:  appsv1.DeploymentStatus{AvailableReplicas: 1},
+			expectCondition: []metav1.Condition{
+				{
+					Type:    string(gwapiv1.GatewayConditionProgrammed),
+					Status:  metav1.ConditionFalse,
+					Reason:  string(gwapiv1.GatewayReasonInvalid),
+					Message: fmt.Sprintf(messageFmtTooManyAddresses, 17),
+				},
+			},
+		},
+		{
+			name:              "not ready gateway with address unavailable pods",
+			serviceAddressNum: 1,
+			deploymentStatus:  appsv1.DeploymentStatus{AvailableReplicas: 0},
+			expectCondition: []metav1.Condition{
+				{
+					Type:    string(gwapiv1.GatewayConditionProgrammed),
+					Status:  metav1.ConditionFalse,
+					Reason:  string(gwapiv1.GatewayReasonNoResources),
+					Message: messageNoResources,
+				},
 			},
 		},
 	}
@@ -168,23 +254,20 @@ func TestGatewayReadyCondition(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
 			gtw := &gwapiv1.Gateway{}
-			if tc.serviceAddress {
-				gtw.Status = gwapiv1.GatewayStatus{
-					Addresses: []gwapiv1.GatewayStatusAddress{
-						{
-							Type:  ptr.To(gwapiv1.IPAddressType),
-							Value: "1.1.1.1",
-						},
-					},
+			gtw.Status.Addresses = make([]gwapiv1.GatewayStatusAddress, tc.serviceAddressNum)
+			for i := 0; i < tc.serviceAddressNum; i++ {
+				gtw.Status.Addresses[i] = gwapiv1.GatewayStatusAddress{
+					Type:  ptr.To(gwapiv1.IPAddressType),
+					Value: strconv.Itoa(i),
 				}
 			}
 
 			deployment := &appsv1.Deployment{Status: tc.deploymentStatus}
-			got := computeGatewayProgrammedCondition(gtw, deployment)
+			updateGatewayProgrammedCondition(gtw, deployment)
 
-			assert.Equal(t, string(gwapiv1.GatewayConditionProgrammed), got.Type)
-			assert.Equal(t, tc.expect.Status, got.Status)
-			assert.Equal(t, tc.expect.Reason, got.Reason)
+			if d := cmp.Diff(tc.expectCondition, gtw.Status.Conditions, cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime")); d != "" {
+				t.Errorf("unexpected condition diff: %s", d)
+			}
 		})
 	}
 }
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.in.yaml
index f8bb9de05..9da4a34e6 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.in.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.in.yaml
@@ -81,6 +81,25 @@ httpRoutes:
       backendRefs:
       - name: service-2
         port: 8080
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-3
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-2
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/test3"
+      backendRefs:
+      - name: service-2
+        port: 8080
 backendTrafficPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: BackendTrafficPolicy
@@ -137,3 +156,19 @@ backendTrafficPolicies:
       type: LeastRequest
       slowStart:
         window: 300s
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    namespace: default
+    name: policy-for-route3
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
+    loadBalancer:
+      type: ConsistentHash
+      consistentHash:
+        type: Cookie
+        cookie:
+          name: "test"
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml
index d1891d883..b2378edf7 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml
@@ -60,6 +60,38 @@ backendTrafficPolicies:
         status: "True"
         type: Accepted
       controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-route3
+    namespace: default
+  spec:
+    loadBalancer:
+      consistentHash:
+        cookie:
+          name: test
+        type: Cookie
+      type: ConsistentHash
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-2
+        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
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: BackendTrafficPolicy
   metadata:
@@ -117,7 +149,7 @@ backendTrafficPolicies:
         type: Accepted
       - lastTransitionTime: null
         message: 'This policy is being overridden by other backendTrafficPolicies
-          for these routes: [default/httproute-1 default/httproute-2]'
+          for these routes: [default/httproute-1 default/httproute-2 default/httproute-3]'
         reason: Overridden
         status: "True"
         type: Overridden
@@ -180,7 +212,7 @@ gateways:
       protocol: HTTP
   status:
     listeners:
-    - attachedRoutes: 2
+    - attachedRoutes: 3
       conditions:
       - lastTransitionTime: null
         message: Sending translated listener configuration to the data plane
@@ -314,6 +346,44 @@ httpRoutes:
         name: gateway-2
         namespace: envoy-gateway
         sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-2
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-2
+        port: 8080
+      matches:
+      - path:
+          value: /test3
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-2
+        namespace: envoy-gateway
+        sectionName: http
 infraIR:
   envoy-gateway/gateway-1:
     proxy:
@@ -430,6 +500,31 @@ xdsIR:
             leastRequest:
               slowStart:
                 window: 5m0s
+      - destination:
+          name: httproute/default/httproute-3/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-3
+          namespace: default
+        name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /test3
+        traffic:
+          loadBalancer:
+            consistentHash:
+              cookie:
+                name: test
       - destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-als-json.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-als-json.in.yaml
index 288501335..4b5caa73f 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog-als-json.in.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-als-json.in.yaml
@@ -110,6 +110,7 @@ services:
     ports:
     - name: grpc
       port: 9000
+      appProtocol: grpc
       protocol: TCP
       targetPort: 9000
 endpointSlices:
@@ -123,6 +124,7 @@ endpointSlices:
   addressType: IPv4
   ports:
   - name: grpc
+    appProtocol: grpc
     protocol: TCP
     port: 9090
   endpoints:
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml
index ea6b29424..0d634113f 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml
@@ -118,6 +118,7 @@ services:
     ports:
     - name: grpc
       port: 9000
+      appProtocol: grpc
       protocol: TCP
       targetPort: 9000
 endpointSlices:
@@ -132,6 +133,7 @@ endpointSlices:
   ports:
   - name: grpc
     protocol: TCP
+    appProtocol: grpc
     port: 9090
   endpoints:
   - addresses:
diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go
index 062808af5..357f6586b 100644
--- a/internal/gatewayapi/translator_test.go
+++ b/internal/gatewayapi/translator_test.go
@@ -239,9 +239,16 @@ func TestTranslate(t *testing.T) {
 						ClusterIP: "3.3.3.3",
 						Ports: []corev1.ServicePort{
 							{
-								Name:       "grpc",
-								Port:       4317,
-								TargetPort: intstr.IntOrString{IntVal: 4317},
+								Name:        "grpc",
+								Port:        4317,
+								TargetPort:  intstr.IntOrString{IntVal: 4317},
+								Protocol:    corev1.ProtocolTCP,
+								AppProtocol: ptr.To("grpc"),
+							},
+							{
+								Name:       "zipkin",
+								Port:       9411,
+								TargetPort: intstr.IntOrString{IntVal: 9411},
 								Protocol:   corev1.ProtocolTCP,
 							},
 						},
@@ -264,6 +271,11 @@ func TestTranslate(t *testing.T) {
 							Port:     ptr.To[int32](4317),
 							Protocol: ptr.To(corev1.ProtocolTCP),
 						},
+						{
+							Name:     ptr.To("zipkin"),
+							Port:     ptr.To[int32](9411),
+							Protocol: ptr.To(corev1.ProtocolTCP),
+						},
 					},
 					Endpoints: []discoveryv1.Endpoint{
 						{
diff --git a/internal/wasm/httpfetcher_test.go b/internal/wasm/httpfetcher_test.go
index a6ba760b1..98fdda500 100644
--- a/internal/wasm/httpfetcher_test.go
+++ b/internal/wasm/httpfetcher_test.go
@@ -158,7 +158,7 @@ func TestWasmHTTPInsecureServer(t *testing.T) {
 			defer ts.Close()
 			fetcher := NewHTTPFetcher(DefaultHTTPRequestTimeout, DefaultHTTPRequestMaxRetries, logging.DefaultLogger(egv1a1.LogLevelInfo))
 			fetcher.initialBackoff = time.Microsecond
-			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 			defer cancel()
 			b, err := fetcher.Fetch(ctx, ts.URL, c.insecure)
 			if c.wantNumRequest != gotNumRequest {
diff --git a/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml b/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml
index 3886f0cfd..998318fdb 100644
--- a/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml
@@ -104,3 +104,16 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
+  - name: "ninth-route"
+    hostname: "*"
+    traffic:
+      loadBalancer:
+        consistentHash:
+          cookie:
+            name: "test"
+    destination:
+      name: "ninth-route-dest"
+      settings:
+      - endpoints:
+        - host: "1.2.3.4"
+          port: 50000
diff --git a/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml b/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml
index a60183dd2..9b4e57fd7 100644
--- a/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml
@@ -24,7 +24,7 @@ tracing:
     - endpoints:
       - host: "zipkin.default.svc.cluster.local"
         port: 9411
-      protocol: "GRPC"
+      protocol: "TCP"
   provider:
     host: zipkin.default.svc.cluster.local
     port: 9411
diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml
index 204667fb0..cc88feed9 100644
--- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml
@@ -140,3 +140,20 @@
   outlierDetection: {}
   perConnectionBufferLimitBytes: 32768
   type: EDS
+- circuitBreakers:
+    thresholds:
+    - maxRetries: 1024
+  commonLbConfig:
+    localityWeightedLbConfig: {}
+  connectTimeout: 10s
+  dnsLookupFamily: V4_ONLY
+  edsClusterConfig:
+    edsConfig:
+      ads: {}
+      resourceApiVersion: V3
+    serviceName: ninth-route-dest
+  lbPolicy: MAGLEV
+  name: ninth-route-dest
+  outlierDetection: {}
+  perConnectionBufferLimitBytes: 32768
+  type: EDS
diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml
index e262710c4..31d553105 100644
--- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml
@@ -94,3 +94,15 @@
     loadBalancingWeight: 1
     locality:
       region: eighth-route-dest/backend/0
+- clusterName: ninth-route-dest
+  endpoints:
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 1.2.3.4
+            portValue: 50000
+      loadBalancingWeight: 1
+    loadBalancingWeight: 1
+    locality:
+      region: ninth-route-dest/backend/0
diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml
index bb34436d3..8fcdb470f 100644
--- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml
@@ -67,3 +67,13 @@
         cluster: eighth-route-dest
         upgradeConfigs:
         - upgradeType: websocket
+    - match:
+        prefix: /
+      name: ninth-route
+      route:
+        cluster: ninth-route-dest
+        hashPolicy:
+        - cookie:
+            name: test
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.clusters.yaml
index b8a1ac3df..a9d0472bf 100644
--- a/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.clusters.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.clusters.yaml
@@ -42,8 +42,3 @@
   perConnectionBufferLimitBytes: 32768
   respectDnsTtl: true
   type: STRICT_DNS
-  typedExtensionProtocolOptions:
-    envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
-      '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
-      explicitHttpConfig:
-        http2ProtocolOptions: {}
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 37a763981..fc824c824 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -446,8 +446,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `rateLimit` | _[RateLimitSpec](#ratelimitspec)_ |  false  | RateLimit allows the user to limit the number of incoming requests<br />to a predefined value based on attributes within the traffic flow. |
 | `loadBalancer` | _[LoadBalancer](#loadbalancer)_ |  false  | LoadBalancer policy to apply when routing traffic from the gateway to<br />the backend endpoints |
 | `proxyProtocol` | _[ProxyProtocol](#proxyprotocol)_ |  false  | ProxyProtocol enables the Proxy Protocol when communicating with the backend. |
@@ -665,8 +666,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `tcpKeepalive` | _[TCPKeepalive](#tcpkeepalive)_ |  false  | TcpKeepalive settings associated with the downstream client connection.<br />If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives.<br />Disabled by default. |
 | `enableProxyProtocol` | _boolean_ |  false  | EnableProxyProtocol interprets the ProxyProtocol header and adds the<br />Client Address into the X-Forwarded-For header.<br />Note Proxy Protocol must be present when this field is set, else the connection<br />is closed. |
 | `clientIPDetection` | _[ClientIPDetectionSettings](#clientipdetectionsettings)_ |  false  | ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. |
@@ -755,6 +757,7 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `type` | _[ConsistentHashType](#consistenthashtype)_ |  true  | ConsistentHashType defines the type of input to hash on. Valid Type values are "SourceIP" or "Header". |
 | `header` | _[Header](#header)_ |  false  | Header configures the header hash policy when the consistent hash type is set to Header. |
+| `cookie` | _[Cookie](#cookie)_ |  false  | Cookie configures the cookie hash policy when the consistent hash type is set to Cookie. |
 | `tableSize` | _integer_ |  false  | The table size for consistent hashing, must be prime number limited to 5000011. |
 
 
@@ -787,6 +790,8 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `name` | _string_ |  true  | Name of the cookie to hash.<br />If this cookie does not exist in the request, Envoy will generate a cookie and set<br />the TTL on the response back to the client based on Layer 4<br />attributes of the backend endpoint, to ensure that these future requests<br />go to the same backend endpoint. Make sure to set the TTL field for this case. |
+| `ttl` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | TTL of the generated cookie if the cookie is not present. This value sets the<br />Max-Age attribute value. |
+| `attributes` | _object (keys:string, values:string)_ |  false  | Additional Attributes to set for the generated cookie. |
 
 
 #### CustomHeaderExtensionSettings
@@ -900,8 +905,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `wasm` | _[Wasm](#wasm) array_ |  false  | Wasm is a list of Wasm extensions to be loaded by the Gateway.<br />Order matters, as the extensions will be loaded in the order they are<br />defined in this list. |
 | `extProc` | _[ExtProc](#extproc) array_ |  false  | ExtProc is an ordered list of external processing filters<br />that should added to the envoy filter chain |
 
@@ -2607,8 +2613,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 
 
 #### Principal
@@ -3320,8 +3327,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `cors` | _[CORS](#cors)_ |  false  | CORS defines the configuration for Cross-Origin Resource Sharing (CORS). |
 | `basicAuth` | _[BasicAuth](#basicauth)_ |  false  | BasicAuth defines the configuration for the HTTP Basic Authentication. |
 | `jwt` | _[JWT](#jwt)_ |  false  | JWT defines the configuration for JSON Web Token (JWT) authentication. |
@@ -3557,6 +3565,26 @@ _Appears in:_
 | `1.3` | TLSv1.3 specifies TLS version 1.3<br /> | 
 
 
+#### TargetSelector
+
+
+
+
+
+_Appears in:_
+- [BackendTrafficPolicySpec](#backendtrafficpolicyspec)
+- [ClientTrafficPolicySpec](#clienttrafficpolicyspec)
+- [EnvoyExtensionPolicySpec](#envoyextensionpolicyspec)
+- [PolicyTargetReferences](#policytargetreferences)
+- [SecurityPolicySpec](#securitypolicyspec)
+
+| Field | Type | Required | Description |
+| ---   | ---  | ---      | ---         |
+| `group` | _[Group](#group)_ |  true  | Group is the group that this selector targets. Defaults to gateway.networking.k8s.io |
+| `kind` | _[Kind](#kind)_ |  true  | Kind is the resource kind that this selector targets. |
+| `matchLabels` | _object (keys:string, values:string)_ |  true  | MatchLabels are the set of label selectors for identifying the targeted resource |
+
+
 #### Timeout
 
 
diff --git a/site/content/en/latest/install/gateway-addons-helm-api.md b/site/content/en/latest/install/gateway-addons-helm-api.md
index 222121967..591af36c3 100644
--- a/site/content/en/latest/install/gateway-addons-helm-api.md
+++ b/site/content/en/latest/install/gateway-addons-helm-api.md
@@ -91,6 +91,7 @@ An Add-ons Helm chart for Envoy Gateway
 | opentelemetry-collector.config.processors.attributes.actions[0].value | string | `"k8s.pod.name, k8s.namespace.name"` |  |
 | opentelemetry-collector.config.receivers.otlp.protocols.grpc.endpoint | string | `"${env:MY_POD_IP}:4317"` |  |
 | opentelemetry-collector.config.receivers.otlp.protocols.http.endpoint | string | `"${env:MY_POD_IP}:4318"` |  |
+| opentelemetry-collector.config.receivers.zipkin.endpoint | string | `"${env:MY_POD_IP}:9411"` |  |
 | opentelemetry-collector.config.service.extensions[0] | string | `"health_check"` |  |
 | opentelemetry-collector.config.service.pipelines.logs.exporters[0] | string | `"loki"` |  |
 | opentelemetry-collector.config.service.pipelines.logs.processors[0] | string | `"attributes"` |  |
@@ -99,6 +100,7 @@ An Add-ons Helm chart for Envoy Gateway
 | opentelemetry-collector.config.service.pipelines.metrics.receivers[0] | string | `"otlp"` |  |
 | opentelemetry-collector.config.service.pipelines.traces.exporters[0] | string | `"otlp"` |  |
 | opentelemetry-collector.config.service.pipelines.traces.receivers[0] | string | `"otlp"` |  |
+| opentelemetry-collector.config.service.pipelines.traces.receivers[1] | string | `"zipkin"` |  |
 | opentelemetry-collector.enabled | bool | `false` |  |
 | opentelemetry-collector.fullnameOverride | string | `"otel-collector"` |  |
 | opentelemetry-collector.mode | string | `"deployment"` |  |
diff --git a/site/content/en/latest/tasks/observability/gateway-exported-metrics.md b/site/content/en/latest/tasks/observability/gateway-exported-metrics.md
index 9878775e1..eb7b560ee 100644
--- a/site/content/en/latest/tasks/observability/gateway-exported-metrics.md
+++ b/site/content/en/latest/tasks/observability/gateway-exported-metrics.md
@@ -17,12 +17,11 @@ they all follow the design of [Watching Components](../../../contributions/desig
 
 Envoy Gateway collects the following metrics in Watching Components:
 
-| Name                                    | Description                                            |
-|-----------------------------------------|--------------------------------------------------------|
-| `watchable_depth`                       | Current depth of watchable map.                        |
-| `watchable_subscribed_duration_seconds` | How long in seconds a subscribed watchable is handled. |
-| `watchable_subscribed_total`            | Total number of subscribed watchable.                  |
-| `watchable_subscribed_errors_total`     | Total number of subscribed watchable errors.           |
+| Name                                   | Description                                                  |
+|----------------------------------------|--------------------------------------------------------------|
+| `watchable_depth`                      | Current depth of watchable map.                              |
+| `watchable_subscribe_duration_seconds` | How long in seconds a subscribed watchable queue is handled. |
+| `watchable_subscribe_total`            | Total number of subscribed watchable queue.                  |
 
 Each metric includes the `runner` label to identify the corresponding components,
 the relationship between label values and components is as follows:
@@ -35,7 +34,7 @@ the relationship between label values and components is as follows:
 | `xds-translator`   | xDS Translator                  |
 | `global-ratelimit` | Global RateLimit xDS Translator |
 
-Metrics may include one or more additional labels, such as `message` etc.
+Metrics may include one or more additional labels, such as `message`, `status` and `reason` etc.
 
 ## Status Updater
 
@@ -43,14 +42,10 @@ Envoy Gateway monitors the status updates of various resources (like `GatewayCla
 
 Envoy Gateway collects the following metrics in Status Updater:
 
-| Name                             | Description                                                                                             |
-|----------------------------------|---------------------------------------------------------------------------------------------------------|
-| `status_update_total`            | Total number of status updates by object kind.                                                          |
-| `status_update_failed_total`     | Number of status updates that failed by object kind.                                                    |
-| `status_update_conflict_total`   | Number of status update conflicts encountered by object kind.                                           |
-| `status_update_success_total`    | Number of status updates that succeeded by object kind.                                                 |
-| `status_update_noop_total`       | Number of status updates that are no-ops by object kind. This is a subset of successful status updates. |
-| `status_update_duration_seconds` | How long a status update takes to finish.                                                               |
+| Name                             | Description                                    |
+|----------------------------------|------------------------------------------------|
+| `status_update_total`            | Total number of status update by object kind.  |
+| `status_update_duration_seconds` | How long a status update takes to finish.      |
 
 Each metric includes `kind` label to identify the corresponding resources.
 
@@ -60,19 +55,14 @@ Envoy Gateway monitors the cache and xDS connection status in xDS Server.
 
 Envoy Gateway collects the following metrics in xDS Server:
 
-| Name                                | Description                                                   |
-|-------------------------------------|---------------------------------------------------------------|
-| `xds_snapshot_creation_total`       | Total number of xds snapshot cache creation.                  |
-| `xds_snapshot_creation_failed`      | Number of xds snapshot cache creation that failed.            |
-| `xds_snapshot_creation_success`     | Number of xds snapshot cache creation that succeed.           |
-| `xds_snapshot_update_total`         | Total number of xds snapshot cache updates by node id.        |
-| `xds_snapshot_update_failed`        | Number of xds snapshot cache updates that failed by node id.  |
-| `xds_snapshot_update_success`       | Number of xds snapshot cache updates that succeed by node id. |
-| `xds_stream_duration_seconds`       | How long a xds stream takes to finish.                        |
-| `xds_delta_stream_duration_seconds` | How long a xds delta stream takes to finish.                  |
+| Name                          | Description                                            |
+|-------------------------------|--------------------------------------------------------|
+| `xds_snapshot_create_total`   | Total number of xds snapshot cache creates.            |
+| `xds_snapshot_update_total`   | Total number of xds snapshot cache updates by node id. |
+| `xds_stream_duration_seconds` | How long a xds stream takes to finish.                 |
 
 - For xDS snapshot cache update and xDS stream connection status, each metric includes `nodeID` label to identify the connection peer.
-- For xDS stream connection status, each metric also includes `streamID` label to identify the connection stream.
+- For xDS stream connection status, each metric also includes `streamID` label to identify the connection stream, and `isDeltaStream` label to identify the delta connection stream.
 
 ## Infrastructure Manager
 
@@ -83,16 +73,25 @@ Envoy Gateway collects the following metrics in Infrastructure Manager:
 | Name                               | Description                                             |
 |------------------------------------|---------------------------------------------------------|
 | `resource_apply_total`             | Total number of applied resources.                      |
-| `resource_apply_failed`            | Number of applied resources that failed.                |
-| `resource_apply_success`           | Number of applied resources that succeed.               |
 | `resource_apply_duration_seconds`  | How long in seconds a resource be applied successfully. |
 | `resource_delete_total`            | Total number of deleted resources.                      |
-| `resource_delete_failed`           | Number of deleted resources that failed.                |
-| `resource_delete_success`          | Number of deleted resources that succeed.               |
 | `resource_delete_duration_seconds` | How long in seconds a resource be deleted successfully. |
 
 Each metric includes the `kind` label to identify the corresponding resources being applied or deleted by Infrastructure Manager.
 
 Metrics may also include `name` and `namespace` label to identify the name and namespace of corresponding Infrastructure Manager.
 
+## Wasm
+
+Envoy Gateway monitors the status of Wasm remote fetch cache.
+
+| Name                      | Description                                      |
+|---------------------------|--------------------------------------------------|
+| `wasm_cache_entries`      | Number of Wasm remote fetch cache entries.       | 
+| `wasm_cache_lookup_total` | Total number of Wasm remote fetch cache lookups. |
+| `wasm_remote_fetch_total` | Total number of Wasm remote fetches and results. |
+
+For metric `wasm_cache_lookup_total`, we are using `hit` label (boolean) to indicate whether the Wasm cache has been hit.
+
+
 [prom-format]: https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format
diff --git a/site/content/en/latest/tasks/observability/proxy-accesslog.md b/site/content/en/latest/tasks/observability/proxy-accesslog.md
new file mode 100644
index 000000000..02596c946
--- /dev/null
+++ b/site/content/en/latest/tasks/observability/proxy-accesslog.md
@@ -0,0 +1,200 @@
+---
+title: "Proxy Access Logs"
+---
+
+Envoy Gateway provides observability for the ControlPlane and the underlying EnvoyProxy instances.
+This task show you how to config proxy access logs.
+
+## Prerequisites
+
+{{< boilerplate o11y_prerequisites >}}
+
+By default, the Service type of `loki` is ClusterIP, you can change it to LoadBalancer type for further usage:
+
+```shell
+kubectl patch service loki -n monitoring -p '{"spec": {"type": "LoadBalancer"}}'
+```
+
+Expose endpoints:
+
+```shell
+LOKI_IP=$(kubectl get svc loki -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
+```
+
+## Default Access Log
+
+If custom format string is not specified, Envoy Gateway uses the following default format:
+
+```json
+{
+  "start_time": "%START_TIME%",
+  "method": "%REQ(:METHOD)%",
+  "x-envoy-origin-path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
+  "protocol": "%PROTOCOL%",
+  "response_code": "%RESPONSE_CODE%",
+  "response_flags": "%RESPONSE_FLAGS%",
+  "response_code_details": "%RESPONSE_CODE_DETAILS%",
+  "connection_termination_details": "%CONNECTION_TERMINATION_DETAILS%",
+  "upstream_transport_failure_reason": "%UPSTREAM_TRANSPORT_FAILURE_REASON%",
+  "bytes_received": "%BYTES_RECEIVED%",
+  "bytes_sent": "%BYTES_SENT%",
+  "duration": "%DURATION%",
+  "x-envoy-upstream-service-time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%",
+  "x-forwarded-for": "%REQ(X-FORWARDED-FOR)%",
+  "user-agent": "%REQ(USER-AGENT)%",
+  "x-request-id": "%REQ(X-REQUEST-ID)%",
+  ":authority": "%REQ(:AUTHORITY)%",
+  "upstream_host": "%UPSTREAM_HOST%",
+  "upstream_cluster": "%UPSTREAM_CLUSTER%",
+  "upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%",
+  "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%",
+  "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%",
+  "requested_server_name": "%REQUESTED_SERVER_NAME%",
+  "route_name": "%ROUTE_NAME%"
+}
+```
+
+> Note: Envoy Gateway disable envoy headers by default, you can enable it by setting `EnableEnvoyHeaders` to `true` in the [ClientTrafficPolicy](../../api/extension_types#backendtrafficpolicy) CRD.
+
+
+Verify logs from loki:
+
+```shell
+curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={job=\"fluentbit\"}" | jq '.data.result[0].values'
+```
+
+## Disable Access Log
+
+If you want to disable it, set the `telemetry.accesslog.disable` to `true` in the `EnvoyProxy` CRD.
+
+```shell
+kubectl apply -f - <<EOF
+apiVersion: gateway.networking.k8s.io/v1
+kind: GatewayClass
+metadata:
+  name: eg
+spec:
+  controllerName: gateway.envoyproxy.io/gatewayclass-controller
+  parametersRef:
+    group: gateway.envoyproxy.io
+    kind: EnvoyProxy
+    name: disable-accesslog
+    namespace: envoy-gateway-system
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: disable-accesslog
+  namespace: envoy-gateway-system
+spec:
+  telemetry:
+    accessLog:
+      disable: true
+EOF
+```
+
+## OpenTelemetry Sink
+
+Envoy Gateway can send logs to OpenTelemetry Sink.
+
+```shell
+kubectl apply -f - <<EOF
+apiVersion: gateway.networking.k8s.io/v1
+kind: GatewayClass
+metadata:
+  name: eg
+spec:
+  controllerName: gateway.envoyproxy.io/gatewayclass-controller
+  parametersRef:
+    group: gateway.envoyproxy.io
+    kind: EnvoyProxy
+    name: otel-access-logging
+    namespace: envoy-gateway-system
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: otel-access-logging
+  namespace: envoy-gateway-system
+spec:
+  telemetry:
+    accessLog:
+      settings:
+        - format:
+            type: Text
+            text: |
+              [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"
+          sinks:
+            - type: OpenTelemetry
+              openTelemetry:
+                host: otel-collector.monitoring.svc.cluster.local
+                port: 4317
+                resources:
+                  k8s.cluster.name: "cluster-1"
+EOF
+```
+
+Verify logs from loki:
+
+```shell
+curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={exporter=\"OTLP\"}" | jq '.data.result[0].values'
+```
+
+## CEL Expressions
+
+Envoy Gateway provides [CEL expressions](https://www.envoyproxy.io/docs/envoy/latest/xds/type/v3/cel.proto.html#common-expression-language-cel-proto) to filter access log . 
+
+For example, you can use the expression `'x-envoy-logged' in request.headers` to filter logs that contain the `x-envoy-logged` header.
+
+```shell 
+kubectl apply -f - <<EOF
+apiVersion: gateway.networking.k8s.io/v1
+kind: GatewayClass
+metadata:
+  name: eg
+spec:
+  controllerName: gateway.envoyproxy.io/gatewayclass-controller
+  parametersRef:
+    group: gateway.envoyproxy.io
+    kind: EnvoyProxy
+    name: otel-access-logging
+    namespace: envoy-gateway-system
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: otel-access-logging
+  namespace: envoy-gateway-system
+spec:
+  telemetry:
+    accessLog:
+      settings:
+        - format:
+            type: Text
+            text: |
+              [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"
+          matches:
+            - "'x-envoy-logged' in request.headers"
+          sinks:
+            - type: OpenTelemetry
+              openTelemetry:
+                host: otel-collector.monitoring.svc.cluster.local
+                port: 4317
+                resources:
+                  k8s.cluster.name: "cluster-1"
+EOF
+```
+
+Verify logs from loki:
+
+```shell
+curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={exporter=\"OTLP\"}" | jq '.data.result[0].values'
+```
+
+
+## Additional Metadata
+
+Envoy Gateway provides additional metadata about the K8s resources that were translated to  certain envoy resources.
+For example, details about the `HTTPRoute` and `GRPCRoute` (kind, group, name, namespace and annotations) are available
+for access log formatter using the `METADATA` operator. To enrich logs, users can add log operator such as:
+`%METADATA(ROUTE:envoy-gateway:resources)%` to their access log format. 
\ No newline at end of file
diff --git a/site/content/en/latest/tasks/observability/proxy-observability.md b/site/content/en/latest/tasks/observability/proxy-observability.md
index 195a4a16b..49237ad1d 100644
--- a/site/content/en/latest/tasks/observability/proxy-observability.md
+++ b/site/content/en/latest/tasks/observability/proxy-observability.md
@@ -3,22 +3,15 @@ title: "Proxy Observability"
 ---
 
 Envoy Gateway provides observability for the ControlPlane and the underlying EnvoyProxy instances.
-This task show you how to config proxy observability, includes metrics, logs, and traces.
+This task show you how to config proxy observability, includes metrics, and traces.
 
 ## Prerequisites
 
 {{< boilerplate o11y_prerequisites >}}
 
-By default, the Service type of `loki` is ClusterIP, you can change it to LoadBalancer type for further usage:
-
-```shell
-kubectl patch service loki -n monitoring -p '{"spec": {"type": "LoadBalancer"}}'
-```
-
 Expose endpoints:
 
 ```shell
-LOKI_IP=$(kubectl get svc loki -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
 TEMPO_IP=$(kubectl get svc tempo -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
 ```
 
@@ -59,47 +52,6 @@ kubectl port-forward pod/$OTEL_POD_NAME -n monitoring 19001:19001
 curl localhost:19001/metrics  | grep "default/backend/rule/0"
 ```
 
-## Logs
-
-If custom format string is not specified, Envoy Gateway uses the following default format:
-
-```json
-{"start_time":"%START_TIME%","method":"%REQ(:METHOD)%","x-envoy-origin-path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","response_code_details":"%RESPONSE_CODE_DETAILS%","connection_termination_details":"%CONNECTION_TERMINATION_DETAILS%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","duration":"%DURATION%","x-envoy-upstream-service-time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","x-forwarded-for":"%REQ(X-FORWARDED-FOR)%","user-agent":"%REQ(USER-AGENT)%","x-request-id":"%REQ(X-REQUEST-ID)%",":authority":"%REQ(:AUTHORITY)%","upstream_host":"%UPSTREAM_HOST%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","requested_server_name":"%REQUESTED_SERVER_NAME%","route_name":"%ROUTE_NAME%"}
-```
-
-> Note: Envoy Gateway disable envoy headers by default, you can enable it by setting `EnableEnvoyHeaders` to `true` in the [ClientTrafficPolicy](../../api/extension_types#backendtrafficpolicy) CRD.
-
-
-Verify logs from loki:
-
-```shell
-curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={job=\"fluentbit\"}" | jq '.data.result[0].values'
-```
-
-If you want to disable it, set the `telemetry.accesslog.disable` to `true` in the `EnvoyProxy` CRD.
-
-```shell
-kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/accesslog/disable-accesslog.yaml
-```
-
-Envoy Gateway can send logs to OpenTelemetry Sink.
-
-```shell
-kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/accesslog/otel-accesslog.yaml
-```
-
-Verify logs from loki:
-
-```shell
-curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={exporter=\"OTLP\"}" | jq '.data.result[0].values'
-```
-
-Envoy Gateway provides additional metadata about the K8s resources that were translated to  certain envoy resources. 
-For example, details about the `HTTPRoute` and `GRPCRoute` (kind, group, name, namespace and annotations) are available 
-for access log formatter using the `METADATA` operator. To enrich logs, users can add log operator such as: 
-`%METADATA(ROUTE:envoy-gateway:resources)%` to their access log format. 
-
-
 ## Traces
 
 By default, Envoy Gateway doesn't send traces to OpenTelemetry Sink.
diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md
index 37a763981..fc824c824 100644
--- a/site/content/zh/latest/api/extension_types.md
+++ b/site/content/zh/latest/api/extension_types.md
@@ -446,8 +446,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `rateLimit` | _[RateLimitSpec](#ratelimitspec)_ |  false  | RateLimit allows the user to limit the number of incoming requests<br />to a predefined value based on attributes within the traffic flow. |
 | `loadBalancer` | _[LoadBalancer](#loadbalancer)_ |  false  | LoadBalancer policy to apply when routing traffic from the gateway to<br />the backend endpoints |
 | `proxyProtocol` | _[ProxyProtocol](#proxyprotocol)_ |  false  | ProxyProtocol enables the Proxy Protocol when communicating with the backend. |
@@ -665,8 +666,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `tcpKeepalive` | _[TCPKeepalive](#tcpkeepalive)_ |  false  | TcpKeepalive settings associated with the downstream client connection.<br />If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives.<br />Disabled by default. |
 | `enableProxyProtocol` | _boolean_ |  false  | EnableProxyProtocol interprets the ProxyProtocol header and adds the<br />Client Address into the X-Forwarded-For header.<br />Note Proxy Protocol must be present when this field is set, else the connection<br />is closed. |
 | `clientIPDetection` | _[ClientIPDetectionSettings](#clientipdetectionsettings)_ |  false  | ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. |
@@ -755,6 +757,7 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `type` | _[ConsistentHashType](#consistenthashtype)_ |  true  | ConsistentHashType defines the type of input to hash on. Valid Type values are "SourceIP" or "Header". |
 | `header` | _[Header](#header)_ |  false  | Header configures the header hash policy when the consistent hash type is set to Header. |
+| `cookie` | _[Cookie](#cookie)_ |  false  | Cookie configures the cookie hash policy when the consistent hash type is set to Cookie. |
 | `tableSize` | _integer_ |  false  | The table size for consistent hashing, must be prime number limited to 5000011. |
 
 
@@ -787,6 +790,8 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `name` | _string_ |  true  | Name of the cookie to hash.<br />If this cookie does not exist in the request, Envoy will generate a cookie and set<br />the TTL on the response back to the client based on Layer 4<br />attributes of the backend endpoint, to ensure that these future requests<br />go to the same backend endpoint. Make sure to set the TTL field for this case. |
+| `ttl` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | TTL of the generated cookie if the cookie is not present. This value sets the<br />Max-Age attribute value. |
+| `attributes` | _object (keys:string, values:string)_ |  false  | Additional Attributes to set for the generated cookie. |
 
 
 #### CustomHeaderExtensionSettings
@@ -900,8 +905,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `wasm` | _[Wasm](#wasm) array_ |  false  | Wasm is a list of Wasm extensions to be loaded by the Gateway.<br />Order matters, as the extensions will be loaded in the order they are<br />defined in this list. |
 | `extProc` | _[ExtProc](#extproc) array_ |  false  | ExtProc is an ordered list of external processing filters<br />that should added to the envoy filter chain |
 
@@ -2607,8 +2613,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 
 
 #### Principal
@@ -3320,8 +3327,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the Gateway resource this policy<br />is being attached to.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway.<br />TargetRef<br /><br />Deprecated: use targetRefs instead |
+| `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ |  true  | TargetRef is the name of the resource this policy is being attached to.<br />This policy and the TargetRef MUST be in the same namespace for this<br />Policy to have effect<br /><br />Deprecated: use targetRefs/targetSelectors instead |
 | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ |  true  | TargetRefs are the names of the Gateway resources this policy<br />is being attached to. |
+| `targetSelectors` | _[TargetSelector](#targetselector) array_ |  true  | TargetSelectors allow targeting resources for this policy based on labels |
 | `cors` | _[CORS](#cors)_ |  false  | CORS defines the configuration for Cross-Origin Resource Sharing (CORS). |
 | `basicAuth` | _[BasicAuth](#basicauth)_ |  false  | BasicAuth defines the configuration for the HTTP Basic Authentication. |
 | `jwt` | _[JWT](#jwt)_ |  false  | JWT defines the configuration for JSON Web Token (JWT) authentication. |
@@ -3557,6 +3565,26 @@ _Appears in:_
 | `1.3` | TLSv1.3 specifies TLS version 1.3<br /> | 
 
 
+#### TargetSelector
+
+
+
+
+
+_Appears in:_
+- [BackendTrafficPolicySpec](#backendtrafficpolicyspec)
+- [ClientTrafficPolicySpec](#clienttrafficpolicyspec)
+- [EnvoyExtensionPolicySpec](#envoyextensionpolicyspec)
+- [PolicyTargetReferences](#policytargetreferences)
+- [SecurityPolicySpec](#securitypolicyspec)
+
+| Field | Type | Required | Description |
+| ---   | ---  | ---      | ---         |
+| `group` | _[Group](#group)_ |  true  | Group is the group that this selector targets. Defaults to gateway.networking.k8s.io |
+| `kind` | _[Kind](#kind)_ |  true  | Kind is the resource kind that this selector targets. |
+| `matchLabels` | _object (keys:string, values:string)_ |  true  | MatchLabels are the set of label selectors for identifying the targeted resource |
+
+
 #### Timeout
 
 
diff --git a/site/content/zh/latest/install/gateway-addons-helm-api.md b/site/content/zh/latest/install/gateway-addons-helm-api.md
index 222121967..591af36c3 100644
--- a/site/content/zh/latest/install/gateway-addons-helm-api.md
+++ b/site/content/zh/latest/install/gateway-addons-helm-api.md
@@ -91,6 +91,7 @@ An Add-ons Helm chart for Envoy Gateway
 | opentelemetry-collector.config.processors.attributes.actions[0].value | string | `"k8s.pod.name, k8s.namespace.name"` |  |
 | opentelemetry-collector.config.receivers.otlp.protocols.grpc.endpoint | string | `"${env:MY_POD_IP}:4317"` |  |
 | opentelemetry-collector.config.receivers.otlp.protocols.http.endpoint | string | `"${env:MY_POD_IP}:4318"` |  |
+| opentelemetry-collector.config.receivers.zipkin.endpoint | string | `"${env:MY_POD_IP}:9411"` |  |
 | opentelemetry-collector.config.service.extensions[0] | string | `"health_check"` |  |
 | opentelemetry-collector.config.service.pipelines.logs.exporters[0] | string | `"loki"` |  |
 | opentelemetry-collector.config.service.pipelines.logs.processors[0] | string | `"attributes"` |  |
@@ -99,6 +100,7 @@ An Add-ons Helm chart for Envoy Gateway
 | opentelemetry-collector.config.service.pipelines.metrics.receivers[0] | string | `"otlp"` |  |
 | opentelemetry-collector.config.service.pipelines.traces.exporters[0] | string | `"otlp"` |  |
 | opentelemetry-collector.config.service.pipelines.traces.receivers[0] | string | `"otlp"` |  |
+| opentelemetry-collector.config.service.pipelines.traces.receivers[1] | string | `"zipkin"` |  |
 | opentelemetry-collector.enabled | bool | `false` |  |
 | opentelemetry-collector.fullnameOverride | string | `"otel-collector"` |  |
 | opentelemetry-collector.mode | string | `"deployment"` |  |
diff --git a/test/benchmark/benchmark_report.md b/test/benchmark/benchmark_report.md
index 4d6d57da1..5821d6784 100644
--- a/test/benchmark/benchmark_report.md
+++ b/test/benchmark/benchmark_report.md
@@ -2,9 +2,9 @@
 
 Benchmark test settings:
 
-|RPS |Connections|Duration (Seconds)|CPU Limits (m)|Memory Limits (MiB)|
-|-   |-          |-                 |-             |-                  |
-|1000|100        |90                |1000          |2048               |
+|RPS  |Connections|Duration (Seconds)|CPU Limits (m)|Memory Limits (MiB)|
+|-    |-          |-                 |-             |-                  |
+|10000|100        |90                |1000          |2048               |
 
 ## Test: ScaleHTTPRoute
 
@@ -20,94 +20,104 @@ Click to see the full results.
 <summary>scale-up-httproutes-10</summary>
 
 ```plaintext
-[2024-06-25 14:23:36.545][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:23:36.545677][1][I] Detected 4 (v)CPUs with affinity..
-[14:23:36.545689][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:23:36.545691][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:23:36.545692][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:25:07.247563][19][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9998444444686 per second.)
-[14:25:07.248019][20][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9975333394178 per second.)
-[14:25:07.248086][22][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.999577777956 per second.)
-[14:25:07.248380][24][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9990666675377 per second.)
-[14:25:07.818186][1][I] Done.
+Warning: 29 02:48:14.546][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[02:48:14.547222][1][I] Detected 4 (v)CPUs with affinity..
+[02:48:14.547235][1][I] Starting 4 threads / event loops. Time limit: 30 seconds.
+[02:48:14.547237][1][I] Global targets: 400 connections and 40000 calls per second.
+[02:48:14.547239][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[02:48:45.249233][18][I] Stopping after 30000 ms. Initiated: 63756 / Completed: 63740. (Completion rate was 2124.6656043338644 per second.)
+[02:48:45.249278][21][I] Stopping after 30000 ms. Initiated: 13846 / Completed: 13844. (Completion rate was 461.4664974622843 per second.)
+[02:48:45.249278][19][I] Stopping after 30000 ms. Initiated: 79156 / Completed: 79137. (Completion rate was 2637.8965707344582 per second.)
+[02:48:45.249494][23][I] Stopping after 30000 ms. Initiated: 20224 / Completed: 20222. (Completion rate was 674.0621055130861 per second.)
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359802 samples)
-  min: 0s 000ms 290us | mean: 0s 000ms 544us | max: 0s 062ms 072us | pstdev: 0s 000ms 863us
+benchmark_http_client.latency_2xx (176582 samples)
+  min: 0s 000ms 358us | mean: 0s 006ms 272us | max: 0s 070ms 623us | pstdev: 0s 011ms 440us
 
   Percentile  Count       Value          
-  0.5         179926      0s 000ms 448us 
-  0.75        269854      0s 000ms 530us 
-  0.8         287861      0s 000ms 552us 
-  0.9         323828      0s 000ms 684us 
-  0.95        341812      0s 000ms 793us 
-  0.990625    356429      0s 001ms 863us 
-  0.99902344  359451      0s 009ms 407us 
+  0.5         88291       0s 002ms 898us 
+  0.75        132439      0s 004ms 643us 
+  0.8         141270      0s 005ms 297us 
+  0.9         158924      0s 008ms 790us 
+  0.95        167754      0s 045ms 185us 
+  0.990625    174928      0s 054ms 206us 
+  0.99902344  176410      0s 059ms 482us 
 
-Queueing and connection setup latency (359802 samples)
-  min: 0s 000ms 002us | mean: 0s 000ms 011us | max: 0s 023ms 417us | pstdev: 0s 000ms 100us
+Queueing and connection setup latency (176621 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 012us | max: 0s 024ms 204us | pstdev: 0s 000ms 165us
+[02:48:50.882431][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 
   Percentile  Count       Value          
-  0.5         179902      0s 000ms 010us 
-  0.75        269909      0s 000ms 010us 
-  0.8         288003      0s 000ms 011us 
-  0.9         323850      0s 000ms 011us 
-  0.95        341822      0s 000ms 012us 
-  0.990625    356429      0s 000ms 029us 
-  0.99902344  359451      0s 000ms 170us 
+  0.5         88528       0s 000ms 003us 
+  0.75        132525      0s 000ms 008us 
+  0.8         141340      0s 000ms 009us 
+  0.9         159044      0s 000ms 010us 
+  0.95        167794      0s 000ms 011us 
+  0.990625    174966      0s 000ms 077us 
+  0.99902344  176449      0s 001ms 431us 
 
-Request start to response end (359802 samples)
-  min: 0s 000ms 289us | mean: 0s 000ms 543us | max: 0s 062ms 072us | pstdev: 0s 000ms 863us
+Request start to response end (176582 samples)
+  min: 0s 000ms 358us | mean: 0s 006ms 271us | max: 0s 070ms 623us | pstdev: 0s 011ms 440us
 
   Percentile  Count       Value          
-  0.5         179915      0s 000ms 448us 
-  0.75        269861      0s 000ms 530us 
-  0.8         287848      0s 000ms 552us 
-  0.9         323824      0s 000ms 683us 
-  0.95        341813      0s 000ms 792us 
-  0.990625    356429      0s 001ms 862us 
-  0.99902344  359451      0s 009ms 406us 
+  0.5         88293       0s 002ms 897us 
+  0.75        132441      0s 004ms 643us 
+  0.8         141267      0s 005ms 296us 
+  0.9         158924      0s 008ms 788us 
+  0.95        167754      0s 045ms 185us 
+  0.990625    174928      0s 054ms 204us 
+  0.99902344  176410      0s 059ms 473us 
 
-Response body size in bytes (359802 samples)
+Response body size in bytes (176582 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359802 samples)
+Response header size in bytes (176582 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Blocking. Results are skewed when significant numbers are reported here. (2 samples)
-  min: 0s 000ms 901us | mean: 0s 001ms 551us | max: 0s 002ms 202us | pstdev: 0s 000ms 650us
+Blocking. Results are skewed when significant numbers are reported here. (53988 samples)
+  min: 0s 000ms 035us | mean: 0s 002ms 220us | max: 0s 067ms 391us | pstdev: 0s 006ms 778us
 
   Percentile  Count       Value          
-  0.5         1           0s 000ms 901us 
+  0.5         26994       0s 000ms 766us 
+  0.75        40492       0s 001ms 732us 
+  0.8         43191       0s 002ms 062us 
+  0.9         48590       0s 003ms 222us 
+  0.95        51289       0s 004ms 958us 
+  0.990625    53482       0s 048ms 125us 
+  0.99902344  53936       0s 055ms 597us 
 
-Initiation to completion (360000 samples)
-  min: 0s 000ms 006us | mean: 0s 000ms 562us | max: 0s 062ms 310us | pstdev: 0s 000ms 883us
+Initiation to completion (176943 samples)
+  min: 0s 000ms 003us | mean: 0s 006ms 351us | max: 0s 071ms 114us | pstdev: 0s 011ms 455us
 
   Percentile  Count       Value          
-  0.5         180016      0s 000ms 465us 
-  0.75        270003      0s 000ms 547us 
-  0.8         288024      0s 000ms 570us 
-  0.9         324002      0s 000ms 702us 
-  0.95        342002      0s 000ms 815us 
-  0.990625    356625      0s 001ms 912us 
-  0.99902344  359649      0s 009ms 617us 
+  0.5         88472       0s 002ms 960us 
+  0.75        132709      0s 004ms 735us 
+  0.8         141556      0s 005ms 408us 
+  0.9         159249      0s 009ms 012us 
+  0.95        168096      0s 045ms 185us 
+  0.990625    175285      0s 054ms 288us 
+  0.99902344  176771      0s 059ms 691us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359802      3997.80
-benchmark.pool_overflow                 198         2.20
-cluster_manager.cluster_added           4           0.04
-default.total_match_count               4           0.04
-membership_change                       4           0.04
-runtime.load_success                    1           0.01
-runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 108         1.20
-upstream_cx_rx_bytes_total              56488914    627653.97
-upstream_cx_total                       108         1.20
-upstream_cx_tx_bytes_total              15471486    171905.23
-upstream_rq_pending_overflow            198         2.20
-upstream_rq_pending_total               108         1.20
-upstream_rq_total                       359802      3997.80
-
+benchmark.http_2xx                      176582      5886.05
+benchmark.pool_overflow                 361         12.03
+cluster_manager.cluster_added           4           0.13
+default.total_match_count               4           0.13
+membership_change                       4           0.13
+runtime.load_success                    1           0.03
+runtime.override_dir_not_exists         1           0.03
+upstream_cx_http1_total                 39          1.30
+upstream_cx_rx_bytes_total              27723374    924110.39
+upstream_cx_total                       39          1.30
+upstream_cx_tx_bytes_total              7594703     253156.20
+upstream_rq_pending_overflow            361         12.03
+upstream_rq_pending_total               39          1.30
+upstream_rq_total                       176621      5887.35
+
+[02:48:55.883737][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[02:49:00.884904][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[02:49:05.885509][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[02:49:05.886786][1][I] Done.
 
 ```
 
@@ -117,90 +127,104 @@ upstream_rq_total                       359802      3997.80
 <summary>scale-up-httproutes-50</summary>
 
 ```plaintext
-[2024-06-25 14:25:18.533][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:25:18.533824][1][I] Detected 4 (v)CPUs with affinity..
-[14:25:18.533833][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:25:18.533836][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:25:18.533837][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:26:49.235731][18][I] Stopping after 89999 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000.0000222222228 per second.)
-[14:26:49.235977][19][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000 per second.)
-[14:26:49.236240][21][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 89999. (Completion rate was 999.9888111119815 per second.)
-[14:26:49.236565][23][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 89999. (Completion rate was 999.9879333448638 per second.)
-[14:26:54.772502][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+Warning: 30 09:50:00.929][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[09:50:00.930463][1][I] Detected 4 (v)CPUs with affinity..
+[09:50:00.930476][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
+[09:50:00.930478][1][I] Global targets: 400 connections and 40000 calls per second.
+[09:50:00.930480][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[09:51:31.632205][18][I] Stopping after 90000 ms. Initiated: 132984 / Completed: 132975. (Completion rate was 1477.4999671666674 per second.)
+[09:51:31.632253][19][I] Stopping after 90000 ms. Initiated: 184337 / Completed: 184323. (Completion rate was 2048.0327871912564 per second.)
+[09:51:31.632393][23][I] Stopping after 90000 ms. Initiated: 119466 / Completed: 119458. (Completion rate was 1327.309400356773 per second.)
+[09:51:31.632493][21][I] Stopping after 90000 ms. Initiated: 98553 / Completed: 98547. (Completion rate was 1094.963746763342 per second.)
+[09:51:37.272832][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359912 samples)
-  min: 0s 000ms 303us | mean: 0s 000ms 508us | max: 0s 031ms 259us | pstdev: 0s 000ms 449us
+benchmark_http_client.latency_2xx (534940 samples)
+  min: 0s 000ms 324us | mean: 0s 006ms 013us | max: 0s 080ms 613us | pstdev: 0s 011ms 899us
 
   Percentile  Count       Value          
-  0.5         179967      0s 000ms 437us 
-  0.75        269938      0s 000ms 509us 
-  0.8         287950      0s 000ms 533us 
-  0.9         323925      0s 000ms 643us 
-  0.95        341919      0s 000ms 735us 
-  0.990625    356538      0s 001ms 526us 
-  0.99902344  359561      0s 006ms 589us 
+  0.5         267470      0s 002ms 663us 
+  0.75        401207      0s 004ms 128us 
+  0.8         427956      0s 004ms 645us 
+  0.9         481449      0s 006ms 891us 
+  0.95        508194      0s 048ms 232us 
+  0.990625    529927      0s 055ms 224us 
+  0.99902344  534418      0s 061ms 255us 
 
-Queueing and connection setup latency (359914 samples)
-  min: 0s 000ms 001us | mean: 0s 000ms 011us | max: 0s 023ms 449us | pstdev: 0s 000ms 080us
+Queueing and connection setup latency (534977 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 012us | max: 0s 026ms 379us | pstdev: 0s 000ms 131us
 
   Percentile  Count       Value          
-  0.5         180198      0s 000ms 010us 
-  0.75        270795      0s 000ms 011us 
-  0.8         288165      0s 000ms 011us 
-  0.9         324019      0s 000ms 011us 
-  0.95        341989      0s 000ms 011us 
-  0.990625    356540      0s 000ms 025us 
-  0.99902344  359564      0s 000ms 159us 
+  0.5         267828      0s 000ms 003us 
+  0.75        401520      0s 000ms 008us 
+  0.8         427993      0s 000ms 009us 
+  0.9         482090      0s 000ms 009us 
+  0.95        508250      0s 000ms 010us 
+  0.990625    529962      0s 000ms 132us 
+  0.99902344  534455      0s 001ms 630us 
 
-Request start to response end (359912 samples)
-  min: 0s 000ms 302us | mean: 0s 000ms 508us | max: 0s 031ms 258us | pstdev: 0s 000ms 448us
+Request start to response end (534940 samples)
+  min: 0s 000ms 324us | mean: 0s 006ms 012us | max: 0s 080ms 613us | pstdev: 0s 011ms 899us
 
   Percentile  Count       Value          
-  0.5         179970      0s 000ms 437us 
-  0.75        269934      0s 000ms 509us 
-  0.8         287943      0s 000ms 533us 
-  0.9         323921      0s 000ms 643us 
-  0.95        341917      0s 000ms 735us 
-  0.990625    356538      0s 001ms 525us 
-  0.99902344  359561      0s 006ms 589us 
+  0.5         267484      0s 002ms 663us 
+  0.75        401210      0s 004ms 127us 
+  0.8         427955      0s 004ms 645us 
+  0.9         481446      0s 006ms 889us 
+  0.95        508195      0s 048ms 232us 
+  0.990625    529929      0s 055ms 224us 
+  0.99902344  534418      0s 061ms 251us 
 
-Response body size in bytes (359912 samples)
+Response body size in bytes (534940 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359912 samples)
+Response header size in bytes (534940 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Initiation to completion (359998 samples)
-  min: 0s 000ms 006us | mean: 0s 000ms 525us | max: 0s 032ms 263us | pstdev: 0s 000ms 461us
+Blocking. Results are skewed when significant numbers are reported here. (176008 samples)
+  min: 0s 000ms 036us | mean: 0s 002ms 044us | max: 0s 073ms 248us | pstdev: 0s 006ms 744us
+
+  Percentile  Count       Value          
+  0.5         88005       0s 000ms 734us 
+  0.75        132008      0s 001ms 534us 
+  0.8         140807      0s 001ms 802us 
+  0.9         158410      0s 002ms 792us 
+  0.95        167208      0s 004ms 190us 
+  0.990625    174359      0s 047ms 886us 
+  0.99902344  175837      0s 053ms 557us 
+
+Initiation to completion (535303 samples)
+  min: 0s 000ms 004us | mean: 0s 006ms 072us | max: 0s 080ms 633us | pstdev: 0s 011ms 900us
 
   Percentile  Count       Value          
-  0.5         180024      0s 000ms 453us 
-  0.75        270017      0s 000ms 526us 
-  0.8         288004      0s 000ms 550us 
-  0.9         323999      0s 000ms 663us 
-  0.95        341999      0s 000ms 753us 
-  0.990625    356624      0s 001ms 571us 
-  0.99902344  359647      0s 006ms 655us 
+  0.5         267665      0s 002ms 717us 
+  0.75        401487      0s 004ms 204us 
+  0.8         428258      0s 004ms 732us 
+  0.9         481775      0s 007ms 022us 
+  0.95        508538      0s 048ms 248us 
+  0.990625    530287      0s 055ms 298us 
+  0.99902344  534781      0s 061ms 421us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359912      3999.02
-benchmark.pool_overflow                 86          0.96
+benchmark.http_2xx                      534940      5943.77
+benchmark.pool_overflow                 363         4.03
 cluster_manager.cluster_added           4           0.04
 default.total_match_count               4           0.04
 membership_change                       4           0.04
 runtime.load_success                    1           0.01
 runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 61          0.68
-upstream_cx_rx_bytes_total              56506184    627846.33
-upstream_cx_total                       61          0.68
-upstream_cx_tx_bytes_total              15476302    171958.87
-upstream_rq_pending_overflow            86          0.96
-upstream_rq_pending_total               61          0.68
-upstream_rq_total                       359914      3999.04
-
-[14:26:59.773726][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
-[14:26:59.775576][1][I] Done.
+upstream_cx_http1_total                 37          0.41
+upstream_cx_rx_bytes_total              83985580    933172.12
+upstream_cx_total                       37          0.41
+upstream_cx_tx_bytes_total              23004011    255599.85
+upstream_rq_pending_overflow            363         4.03
+upstream_rq_pending_total               37          0.41
+upstream_rq_total                       534977      5944.18
+
+[09:51:42.273918][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:51:47.274994][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:51:52.275699][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:51:52.277010][1][I] Done.
 
 ```
 
@@ -210,90 +234,104 @@ upstream_rq_total                       359914      3999.04
 <summary>scale-up-httproutes-100</summary>
 
 ```plaintext
-[2024-06-25 14:27:18.024][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:27:18.024969][1][I] Detected 4 (v)CPUs with affinity..
-[14:27:18.024981][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:27:18.024984][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:27:18.024985][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:28:48.726723][18][I] Stopping after 89999 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000.0000111111112 per second.)
-[14:28:48.726970][19][I] Stopping after 89999 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000.0000222222228 per second.)
-[14:28:48.727250][21][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 89999. (Completion rate was 999.9885555593705 per second.)
-[14:28:48.727579][23][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 89999. (Completion rate was 999.9878444571402 per second.)
-[14:28:54.260999][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+Warning: 30 09:52:08.843][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[09:52:08.843704][1][I] Detected 4 (v)CPUs with affinity..
+[09:52:08.843716][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
+[09:52:08.843719][1][I] Global targets: 400 connections and 40000 calls per second.
+[09:52:08.843720][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[09:53:39.545479][18][I] Stopping after 90000 ms. Initiated: 60881 / Completed: 60878. (Completion rate was 676.421921590257 per second.)
+[09:53:39.545649][23][I] Stopping after 90000 ms. Initiated: 77409 / Completed: 77407. (Completion rate was 860.076458993874 per second.)
+[09:53:39.545773][19][I] Stopping after 90000 ms. Initiated: 271217 / Completed: 271198. (Completion rate was 3013.300631521137 per second.)
+[09:53:39.546416][21][I] Stopping after 90000 ms. Initiated: 123329 / Completed: 123321. (Completion rate was 1370.219189626365 per second.)
+[09:53:45.183623][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359869 samples)
-  min: 0s 000ms 301us | mean: 0s 000ms 514us | max: 0s 029ms 035us | pstdev: 0s 000ms 431us
+benchmark_http_client.latency_2xx (532441 samples)
+  min: 0s 000ms 359us | mean: 0s 006ms 029us | max: 0s 090ms 263us | pstdev: 0s 011ms 870us
 
   Percentile  Count       Value          
-  0.5         179965      0s 000ms 444us 
-  0.75        269904      0s 000ms 518us 
-  0.8         287910      0s 000ms 540us 
-  0.9         323888      0s 000ms 641us 
-  0.95        341879      0s 000ms 744us 
-  0.990625    356497      0s 001ms 522us 
-  0.99902344  359518      0s 006ms 553us 
+  0.5         266227      0s 002ms 698us 
+  0.75        399344      0s 004ms 228us 
+  0.8         425959      0s 004ms 757us 
+  0.9         479199      0s 007ms 042us 
+  0.95        505821      0s 047ms 982us 
+  0.990625    527453      0s 055ms 048us 
+  0.99902344  531922      0s 060ms 678us 
 
-Queueing and connection setup latency (359871 samples)
-  min: 0s 000ms 001us | mean: 0s 000ms 011us | max: 0s 027ms 366us | pstdev: 0s 000ms 058us
+Queueing and connection setup latency (532473 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 011us | max: 0s 023ms 204us | pstdev: 0s 000ms 126us
 
   Percentile  Count       Value          
-  0.5         179998      0s 000ms 010us 
-  0.75        271128      0s 000ms 011us 
-  0.8         288699      0s 000ms 011us 
-  0.9         324073      0s 000ms 011us 
-  0.95        341895      0s 000ms 012us 
-  0.990625    356498      0s 000ms 029us 
-  0.99902344  359520      0s 000ms 166us 
+  0.5         267630      0s 000ms 003us 
+  0.75        399579      0s 000ms 008us 
+  0.8         426987      0s 000ms 009us 
+  0.9         479713      0s 000ms 009us 
+  0.95        505878      0s 000ms 010us 
+  0.990625    527482      0s 000ms 040us 
+  0.99902344  531955      0s 001ms 391us 
 
-Request start to response end (359869 samples)
-  min: 0s 000ms 301us | mean: 0s 000ms 513us | max: 0s 029ms 035us | pstdev: 0s 000ms 431us
+Request start to response end (532441 samples)
+  min: 0s 000ms 359us | mean: 0s 006ms 028us | max: 0s 090ms 263us | pstdev: 0s 011ms 870us
 
   Percentile  Count       Value          
-  0.5         179935      0s 000ms 444us 
-  0.75        269906      0s 000ms 517us 
-  0.8         287896      0s 000ms 539us 
-  0.9         323883      0s 000ms 641us 
-  0.95        341876      0s 000ms 743us 
-  0.990625    356496      0s 001ms 521us 
-  0.99902344  359518      0s 006ms 552us 
+  0.5         266221      0s 002ms 697us 
+  0.75        399332      0s 004ms 227us 
+  0.8         425959      0s 004ms 757us 
+  0.9         479199      0s 007ms 042us 
+  0.95        505824      0s 047ms 982us 
+  0.990625    527450      0s 055ms 046us 
+  0.99902344  531922      0s 060ms 678us 
 
-Response body size in bytes (359869 samples)
+Response body size in bytes (532441 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359869 samples)
+Response header size in bytes (532441 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Initiation to completion (359998 samples)
-  min: 0s 000ms 007us | mean: 0s 000ms 532us | max: 0s 029ms 055us | pstdev: 0s 000ms 451us
+Blocking. Results are skewed when significant numbers are reported here. (183352 samples)
+  min: 0s 000ms 033us | mean: 0s 001ms 962us | max: 0s 084ms 799us | pstdev: 0s 006ms 606us
+
+  Percentile  Count       Value          
+  0.5         91683       0s 000ms 726us 
+  0.75        137514      0s 001ms 420us 
+  0.8         146685      0s 001ms 667us 
+  0.9         165017      0s 002ms 581us 
+  0.95        174186      0s 003ms 882us 
+  0.990625    181634      0s 047ms 661us 
+  0.99902344  183173      0s 053ms 168us 
+
+Initiation to completion (532804 samples)
+  min: 0s 000ms 001us | mean: 0s 006ms 088us | max: 0s 090ms 275us | pstdev: 0s 011ms 873us
 
   Percentile  Count       Value          
-  0.5         180023      0s 000ms 461us 
-  0.75        270008      0s 000ms 535us 
-  0.8         288030      0s 000ms 557us 
-  0.9         324004      0s 000ms 661us 
-  0.95        341999      0s 000ms 763us 
-  0.990625    356624      0s 001ms 570us 
-  0.99902344  359647      0s 007ms 023us 
+  0.5         266426      0s 002ms 753us 
+  0.75        399604      0s 004ms 306us 
+  0.8         426251      0s 004ms 841us 
+  0.9         479526      0s 007ms 164us 
+  0.95        506172      0s 048ms 007us 
+  0.990625    527811      0s 055ms 113us 
+  0.99902344  532284      0s 060ms 801us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359869      3998.54
-benchmark.pool_overflow                 129         1.43
+benchmark.http_2xx                      532441      5915.99
+benchmark.pool_overflow                 363         4.03
 cluster_manager.cluster_added           4           0.04
 default.total_match_count               4           0.04
 membership_change                       4           0.04
 runtime.load_success                    1           0.01
 runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 63          0.70
-upstream_cx_rx_bytes_total              56499433    627771.26
-upstream_cx_total                       63          0.70
-upstream_cx_tx_bytes_total              15474453    171938.31
-upstream_rq_pending_overflow            129         1.43
-upstream_rq_pending_total               63          0.70
-upstream_rq_total                       359871      3998.57
-
-[14:28:59.262084][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
-[14:28:59.263795][1][I] Done.
+upstream_cx_http1_total                 37          0.41
+upstream_cx_rx_bytes_total              83593237    928810.08
+upstream_cx_total                       37          0.41
+upstream_cx_tx_bytes_total              22896339    254402.76
+upstream_rq_pending_overflow            363         4.03
+upstream_rq_pending_total               37          0.41
+upstream_rq_total                       532473      5916.34
+
+[09:53:50.184479][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:53:55.185619][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:54:00.186411][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:54:00.187569][1][I] Done.
 
 ```
 
@@ -303,88 +341,104 @@ upstream_rq_total                       359871      3998.57
 <summary>scale-up-httproutes-300</summary>
 
 ```plaintext
-[2024-06-25 14:32:23.491][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:32:23.491963][1][I] Detected 4 (v)CPUs with affinity..
-[14:32:23.491978][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:32:23.491980][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:32:23.491981][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:33:54.193887][18][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9999888888891 per second.)
-[14:33:54.194133][19][I] Stopping after 89999 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000.0000222222228 per second.)
-[14:33:54.194387][21][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9999888888891 per second.)
-[14:33:54.194633][23][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000 per second.)
-[14:33:54.712898][1][I] Done.
+Warning: 30 09:57:17.615][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[09:57:17.615763][1][I] Detected 4 (v)CPUs with affinity..
+[09:57:17.615775][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
+[09:57:17.615778][1][I] Global targets: 400 connections and 40000 calls per second.
+[09:57:17.615779][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[09:58:48.317519][18][I] Stopping after 90000 ms. Initiated: 141701 / Completed: 141691. (Completion rate was 1574.3439371558425 per second.)
+[09:58:48.317519][19][I] Stopping after 90000 ms. Initiated: 142076 / Completed: 142066. (Completion rate was 1578.5110584940758 per second.)
+[09:58:48.317557][21][I] Stopping after 90000 ms. Initiated: 169359 / Completed: 169346. (Completion rate was 1881.6218249909482 per second.)
+[09:58:48.317726][23][I] Stopping after 90000 ms. Initiated: 73891 / Completed: 73887. (Completion rate was 820.9651798075076 per second.)
+[09:58:53.963287][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359845 samples)
-  min: 0s 000ms 302us | mean: 0s 000ms 507us | max: 0s 019ms 987us | pstdev: 0s 000ms 380us
+benchmark_http_client.latency_2xx (526627 samples)
+  min: 0s 000ms 368us | mean: 0s 006ms 116us | max: 0s 085ms 676us | pstdev: 0s 012ms 060us
 
   Percentile  Count       Value          
-  0.5         179931      0s 000ms 440us 
-  0.75        269886      0s 000ms 512us 
-  0.8         287876      0s 000ms 533us 
-  0.9         323864      0s 000ms 637us 
-  0.95        341854      0s 000ms 734us 
-  0.990625    356472      0s 001ms 469us 
-  0.99902344  359494      0s 006ms 259us 
+  0.5         263331      0s 002ms 692us 
+  0.75        394974      0s 004ms 203us 
+  0.8         421305      0s 004ms 735us 
+  0.9         473966      0s 007ms 143us 
+  0.95        500299      0s 048ms 519us 
+  0.990625    521693      0s 055ms 746us 
+  0.99902344  526114      0s 062ms 912us 
 
-Queueing and connection setup latency (359845 samples)
-  min: 0s 000ms 001us | mean: 0s 000ms 011us | max: 0s 017ms 634us | pstdev: 0s 000ms 043us
+Queueing and connection setup latency (526664 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 012us | max: 0s 019ms 310us | pstdev: 0s 000ms 136us
 
   Percentile  Count       Value          
-  0.5         180160      0s 000ms 010us 
-  0.75        270791      0s 000ms 010us 
-  0.8         287918      0s 000ms 011us 
-  0.9         324365      0s 000ms 011us 
-  0.95        341940      0s 000ms 011us 
-  0.990625    356473      0s 000ms 027us 
-  0.99902344  359494      0s 000ms 167us 
+  0.5         263616      0s 000ms 003us 
+  0.75        395207      0s 000ms 008us 
+  0.8         421679      0s 000ms 009us 
+  0.9         474013      0s 000ms 009us 
+  0.95        500359      0s 000ms 010us 
+  0.990625    521727      0s 000ms 127us 
+  0.99902344  526150      0s 001ms 624us 
 
-Request start to response end (359845 samples)
-  min: 0s 000ms 302us | mean: 0s 000ms 506us | max: 0s 019ms 987us | pstdev: 0s 000ms 380us
+Request start to response end (526627 samples)
+  min: 0s 000ms 368us | mean: 0s 006ms 116us | max: 0s 085ms 676us | pstdev: 0s 012ms 060us
 
   Percentile  Count       Value          
-  0.5         179923      0s 000ms 440us 
-  0.75        269893      0s 000ms 511us 
-  0.8         287905      0s 000ms 533us 
-  0.9         323861      0s 000ms 636us 
-  0.95        341854      0s 000ms 733us 
-  0.990625    356472      0s 001ms 468us 
-  0.99902344  359494      0s 006ms 259us 
+  0.5         263324      0s 002ms 692us 
+  0.75        394984      0s 004ms 203us 
+  0.8         421305      0s 004ms 734us 
+  0.9         473966      0s 007ms 142us 
+  0.95        500299      0s 048ms 519us 
+  0.990625    521693      0s 055ms 746us 
+  0.99902344  526113      0s 062ms 910us 
 
-Response body size in bytes (359845 samples)
+Response body size in bytes (526627 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359845 samples)
+Response header size in bytes (526627 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Initiation to completion (360000 samples)
-  min: 0s 000ms 007us | mean: 0s 000ms 525us | max: 0s 020ms 035us | pstdev: 0s 000ms 409us
+Blocking. Results are skewed when significant numbers are reported here. (178472 samples)
+  min: 0s 000ms 034us | mean: 0s 002ms 016us | max: 0s 085ms 700us | pstdev: 0s 006ms 753us
+
+  Percentile  Count       Value          
+  0.5         89237       0s 000ms 732us 
+  0.75        133855      0s 001ms 469us 
+  0.8         142779      0s 001ms 727us 
+  0.9         160630      0s 002ms 687us 
+  0.95        169550      0s 004ms 042us 
+  0.990625    176799      0s 048ms 060us 
+  0.99902344  178298      0s 054ms 435us 
+
+Initiation to completion (526990 samples)
+  min: 0s 000ms 004us | mean: 0s 006ms 174us | max: 0s 085ms 700us | pstdev: 0s 012ms 062us
 
   Percentile  Count       Value          
-  0.5         180011      0s 000ms 456us 
-  0.75        270028      0s 000ms 529us 
-  0.8         288004      0s 000ms 550us 
-  0.9         324006      0s 000ms 656us 
-  0.95        342005      0s 000ms 751us 
-  0.990625    356625      0s 001ms 525us 
-  0.99902344  359649      0s 006ms 569us 
+  0.5         263496      0s 002ms 745us 
+  0.75        395254      0s 004ms 278us 
+  0.8         421594      0s 004ms 818us 
+  0.9         474295      0s 007ms 277us 
+  0.95        500644      0s 048ms 537us 
+  0.990625    522050      0s 055ms 818us 
+  0.99902344  526476      0s 062ms 992us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359845      3998.28
-benchmark.pool_overflow                 155         1.72
+benchmark.http_2xx                      526627      5851.41
+benchmark.pool_overflow                 363         4.03
 cluster_manager.cluster_added           4           0.04
 default.total_match_count               4           0.04
 membership_change                       4           0.04
 runtime.load_success                    1           0.01
 runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 62          0.69
-upstream_cx_rx_bytes_total              56495665    627729.61
-upstream_cx_total                       62          0.69
-upstream_cx_tx_bytes_total              15473335    171925.94
-upstream_rq_pending_overflow            155         1.72
-upstream_rq_pending_total               62          0.69
-upstream_rq_total                       359845      3998.28
-
+upstream_cx_http1_total                 37          0.41
+upstream_cx_rx_bytes_total              82680439    918671.00
+upstream_cx_total                       37          0.41
+upstream_cx_tx_bytes_total              22646552    251628.21
+upstream_rq_pending_overflow            363         4.03
+upstream_rq_pending_total               37          0.41
+upstream_rq_total                       526664      5851.82
+
+[09:58:58.964269][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:59:03.965258][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:59:08.966199][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[09:59:08.967339][1][I] Done.
 
 ```
 
@@ -394,92 +448,104 @@ upstream_rq_total                       359845      3998.28
 <summary>scale-up-httproutes-500</summary>
 
 ```plaintext
-[2024-06-25 14:38:43.691][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:38:43.691938][1][I] Detected 4 (v)CPUs with affinity..
-[14:38:43.691951][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:38:43.691953][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:38:43.691954][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:40:14.393764][18][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 89999. (Completion rate was 999.9885666703507 per second.)
-[14:40:14.393981][19][I] Stopping after 89999 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000.0000555555587 per second.)
-[14:40:14.394312][21][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9992666672044 per second.)
-[14:40:14.394484][23][I] Stopping after 89999 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 1000.0000333333344 per second.)
-[14:40:19.954533][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+Warning: 30 10:05:50.181][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[10:05:50.182352][1][I] Detected 4 (v)CPUs with affinity..
+[10:05:50.182365][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
+[10:05:50.182367][1][I] Global targets: 400 connections and 40000 calls per second.
+[10:05:50.182369][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[10:07:20.884276][21][I] Stopping after 90000 ms. Initiated: 93542 / Completed: 93539. (Completion rate was 1039.3210789690352 per second.)
+[10:07:20.884582][19][I] Stopping after 90000 ms. Initiated: 180072 / Completed: 180060. (Completion rate was 2000.6570635127619 per second.)
+[10:07:20.884601][18][I] Stopping after 90000 ms. Initiated: 101770 / Completed: 101764. (Completion rate was 1130.7051560639559 per second.)
+[10:07:20.884602][23][I] Stopping after 90000 ms. Initiated: 140594 / Completed: 140587. (Completion rate was 1562.0708005282022 per second.)
+[10:07:26.528168][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359743 samples)
-  min: 0s 000ms 311us | mean: 0s 000ms 566us | max: 0s 064ms 673us | pstdev: 0s 001ms 003us
+benchmark_http_client.latency_2xx (515587 samples)
+  min: 0s 000ms 352us | mean: 0s 006ms 243us | max: 0s 103ms 198us | pstdev: 0s 012ms 343us
 
   Percentile  Count       Value          
-  0.5         179890      0s 000ms 441us 
-  0.75        269813      0s 000ms 519us 
-  0.8         287802      0s 000ms 544us 
-  0.9         323771      0s 000ms 684us 
-  0.95        341757      0s 000ms 790us 
-  0.990625    356372      0s 002ms 465us 
-  0.99902344  359392      0s 016ms 404us 
+  0.5         257799      0s 002ms 698us 
+  0.75        386691      0s 004ms 155us 
+  0.8         412474      0s 004ms 697us 
+  0.9         464029      0s 007ms 193us 
+  0.95        489815      0s 048ms 922us 
+  0.990625    510755      0s 056ms 528us 
+  0.99902344  515084      0s 067ms 747us 
 
-Queueing and connection setup latency (359744 samples)
-  min: 0s 000ms 001us | mean: 0s 000ms 011us | max: 0s 040ms 116us | pstdev: 0s 000ms 093us
+Queueing and connection setup latency (515615 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 012us | max: 0s 020ms 386us | pstdev: 0s 000ms 125us
 
   Percentile  Count       Value          
-  0.5         180015      0s 000ms 010us 
-  0.75        269817      0s 000ms 011us 
-  0.8         288758      0s 000ms 011us 
-  0.9         324218      0s 000ms 011us 
-  0.95        341791      0s 000ms 012us 
-  0.990625    356372      0s 000ms 029us 
-  0.99902344  359393      0s 000ms 172us 
+  0.5         258414      0s 000ms 003us 
+  0.75        386829      0s 000ms 008us 
+  0.8         412620      0s 000ms 009us 
+  0.9         464074      0s 000ms 009us 
+  0.95        489886      0s 000ms 010us 
+  0.990625    510782      0s 000ms 123us 
+  0.99902344  515112      0s 001ms 602us 
 
-Request start to response end (359743 samples)
-  min: 0s 000ms 311us | mean: 0s 000ms 566us | max: 0s 064ms 673us | pstdev: 0s 001ms 003us
+Request start to response end (515587 samples)
+  min: 0s 000ms 352us | mean: 0s 006ms 243us | max: 0s 103ms 194us | pstdev: 0s 012ms 343us
 
   Percentile  Count       Value          
-  0.5         179874      0s 000ms 441us 
-  0.75        269820      0s 000ms 519us 
-  0.8         287800      0s 000ms 544us 
-  0.9         323772      0s 000ms 684us 
-  0.95        341758      0s 000ms 790us 
-  0.990625    356372      0s 002ms 464us 
-  0.99902344  359392      0s 016ms 404us 
+  0.5         257802      0s 002ms 698us 
+  0.75        386698      0s 004ms 155us 
+  0.8         412470      0s 004ms 697us 
+  0.9         464031      0s 007ms 192us 
+  0.95        489808      0s 048ms 920us 
+  0.990625    510756      0s 056ms 528us 
+  0.99902344  515084      0s 067ms 747us 
 
-Response body size in bytes (359743 samples)
+Response body size in bytes (515587 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359743 samples)
+Response header size in bytes (515587 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Blocking. Results are skewed when significant numbers are reported here. (1 samples)
-  min: 0s 001ms 331us | mean: 0s 001ms 331us | max: 0s 001ms 331us | pstdev: 0s 000ms 000us
+Blocking. Results are skewed when significant numbers are reported here. (165055 samples)
+  min: 0s 000ms 036us | mean: 0s 002ms 180us | max: 0s 090ms 710us | pstdev: 0s 007ms 128us
+
+  Percentile  Count       Value          
+  0.5         82528       0s 000ms 765us 
+  0.75        123792      0s 001ms 622us 
+  0.8         132045      0s 001ms 906us 
+  0.9         148550      0s 002ms 915us 
+  0.95        156804      0s 004ms 402us 
+  0.990625    163510      0s 048ms 775us 
+  0.99902344  164894      0s 058ms 019us 
 
-Initiation to completion (359999 samples)
-  min: 0s 000ms 005us | mean: 0s 000ms 593us | max: 0s 064ms 710us | pstdev: 0s 001ms 145us
+Initiation to completion (515950 samples)
+  min: 0s 000ms 004us | mean: 0s 006ms 300us | max: 0s 103ms 215us | pstdev: 0s 012ms 342us
 
   Percentile  Count       Value          
-  0.5         180029      0s 000ms 458us 
-  0.75        270014      0s 000ms 537us 
-  0.8         288011      0s 000ms 562us 
-  0.9         324008      0s 000ms 703us 
-  0.95        342000      0s 000ms 813us 
-  0.990625    356625      0s 002ms 640us 
-  0.99902344  359648      0s 018ms 319us 
+  0.5         257987      0s 002ms 750us 
+  0.75        386970      0s 004ms 235us 
+  0.8         412760      0s 004ms 784us 
+  0.9         464357      0s 007ms 323us 
+  0.95        490153      0s 048ms 945us 
+  0.990625    511115      0s 056ms 580us 
+  0.99902344  515447      0s 067ms 813us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359743      3997.14
-benchmark.pool_overflow                 256         2.84
+benchmark.http_2xx                      515587      5728.72
+benchmark.pool_overflow                 363         4.03
 cluster_manager.cluster_added           4           0.04
 default.total_match_count               4           0.04
 membership_change                       4           0.04
 runtime.load_success                    1           0.01
 runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 96          1.07
-upstream_cx_rx_bytes_total              56479651    627551.52
-upstream_cx_total                       96          1.07
-upstream_cx_tx_bytes_total              15468992    171877.65
-upstream_rq_pending_overflow            256         2.84
-upstream_rq_pending_total               96          1.07
-upstream_rq_total                       359744      3997.15
-
-[14:40:19.962562][1][I] Done.
+upstream_cx_http1_total                 37          0.41
+upstream_cx_rx_bytes_total              80947159    899409.36
+upstream_cx_total                       37          0.41
+upstream_cx_tx_bytes_total              22171445    246348.42
+upstream_rq_pending_overflow            363         4.03
+upstream_rq_pending_total               37          0.41
+upstream_rq_total                       515615      5729.03
+
+[10:07:31.529027][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:07:36.530025][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:07:41.530832][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:07:41.532165][1][I] Done.
 
 ```
 
@@ -489,101 +555,103 @@ upstream_rq_total                       359744      3997.15
 <summary>scale-down-httproutes-300</summary>
 
 ```plaintext
-[2024-06-25 14:40:47.629][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:40:47.629688][1][I] Detected 4 (v)CPUs with affinity..
-[14:40:47.629700][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:40:47.629703][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:40:47.629704][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:42:18.331523][18][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9990222231783 per second.)
-[14:42:18.331681][19][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9999777777783 per second.)
-[14:42:18.331935][21][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 89999. (Completion rate was 999.988855555927 per second.)
-[14:42:18.332255][23][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.999166667361 per second.)
-[14:42:23.961708][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+Warning: 30 10:08:14.153][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[10:08:14.154484][1][I] Detected 4 (v)CPUs with affinity..
+[10:08:14.154499][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
+[10:08:14.154502][1][I] Global targets: 400 connections and 40000 calls per second.
+[10:08:14.154504][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[10:09:44.857305][21][I] Stopping after 90000 ms. Initiated: 120108 / Completed: 120100. (Completion rate was 1334.4432137912584 per second.)
+[10:09:44.857423][23][I] Stopping after 90000 ms. Initiated: 54818 / Completed: 54817. (Completion rate was 609.0765799271705 per second.)
+[10:09:44.857655][18][I] Stopping after 90000 ms. Initiated: 191822 / Completed: 191822. (Completion rate was 2131.3440462977055 per second.)
+[10:09:44.858450][19][I] Stopping after 90001 ms. Initiated: 150329 / Completed: 150327. (Completion rate was 1670.2767089192257 per second.)
+[10:09:50.501933][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359722 samples)
-  min: 0s 000ms 303us | mean: 0s 001ms 203us | max: 0s 121ms 311us | pstdev: 0s 006ms 029us
+benchmark_http_client.latency_2xx (516703 samples)
+  min: 0s 000ms 339us | mean: 0s 006ms 221us | max: 0s 096ms 722us | pstdev: 0s 011ms 937us
 
   Percentile  Count       Value          
-  0.5         179885      0s 000ms 456us 
-  0.75        269810      0s 000ms 543us 
-  0.8         287781      0s 000ms 570us 
-  0.9         323750      0s 000ms 749us 
-  0.95        341736      0s 001ms 344us 
-  0.990625    356350      0s 016ms 743us 
-  0.99902344  359371      0s 083ms 783us 
+  0.5         258358      0s 002ms 750us 
+  0.75        387543      0s 004ms 382us 
+  0.8         413372      0s 004ms 969us 
+  0.9         465035      0s 007ms 728us 
+  0.95        490869      0s 047ms 640us 
+  0.990625    511859      0s 055ms 703us 
+  0.99902344  516199      0s 065ms 038us 
 
-Queueing and connection setup latency (359723 samples)
-  min: 0s 000ms 001us | mean: 0s 000ms 012us | max: 0s 041ms 897us | pstdev: 0s 000ms 131us
+Queueing and connection setup latency (516714 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 012us | max: 0s 019ms 922us | pstdev: 0s 000ms 135us
 
   Percentile  Count       Value          
-  0.5         179921      0s 000ms 010us 
-  0.75        270953      0s 000ms 011us 
-  0.8         288381      0s 000ms 011us 
-  0.9         323867      0s 000ms 011us 
-  0.95        341759      0s 000ms 012us 
-  0.990625    356351      0s 000ms 032us 
-  0.99902344  359372      0s 000ms 206us 
+  0.5         259348      0s 000ms 003us 
+  0.75        387676      0s 000ms 008us 
+  0.8         413511      0s 000ms 009us 
+  0.9         465475      0s 000ms 009us 
+  0.95        490880      0s 000ms 010us 
+  0.990625    511870      0s 000ms 042us 
+  0.99902344  516210      0s 001ms 596us 
 
-Request start to response end (359722 samples)
-  min: 0s 000ms 302us | mean: 0s 001ms 202us | max: 0s 121ms 311us | pstdev: 0s 006ms 029us
+Request start to response end (516703 samples)
+  min: 0s 000ms 339us | mean: 0s 006ms 221us | max: 0s 096ms 722us | pstdev: 0s 011ms 937us
 
   Percentile  Count       Value          
-  0.5         179877      0s 000ms 456us 
-  0.75        269810      0s 000ms 542us 
-  0.8         287783      0s 000ms 570us 
-  0.9         323752      0s 000ms 748us 
-  0.95        341736      0s 001ms 344us 
-  0.990625    356350      0s 016ms 742us 
-  0.99902344  359371      0s 083ms 783us 
+  0.5         258360      0s 002ms 750us 
+  0.75        387541      0s 004ms 382us 
+  0.8         413365      0s 004ms 968us 
+  0.9         465034      0s 007ms 726us 
+  0.95        490870      0s 047ms 640us 
+  0.990625    511859      0s 055ms 703us 
+  0.99902344  516199      0s 065ms 038us 
 
-Response body size in bytes (359722 samples)
+Response body size in bytes (516703 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359722 samples)
+Response header size in bytes (516703 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Blocking. Results are skewed when significant numbers are reported here. (1022 samples)
-  min: 0s 000ms 045us | mean: 0s 006ms 403us | max: 0s 099ms 049us | pstdev: 0s 015ms 130us
+Blocking. Results are skewed when significant numbers are reported here. (170680 samples)
+  min: 0s 000ms 034us | mean: 0s 002ms 108us | max: 0s 090ms 091us | pstdev: 0s 006ms 769us
 
   Percentile  Count       Value          
-  0.5         511         0s 001ms 012us 
-  0.75        767         0s 003ms 262us 
-  0.8         818         0s 004ms 782us 
-  0.9         920         0s 015ms 482us 
-  0.95        971         0s 047ms 316us 
-  0.990625    1013        0s 075ms 657us 
-  0.99902344  1022        0s 099ms 049us 
+  0.5         85340       0s 000ms 756us 
+  0.75        128013      0s 001ms 581us 
+  0.8         136546      0s 001ms 864us 
+  0.9         153612      0s 002ms 914us 
+  0.95        162148      0s 004ms 492us 
+  0.990625    169080      0s 047ms 810us 
+  0.99902344  170514      0s 055ms 848us 
 
-Initiation to completion (359999 samples)
-  min: 0s 000ms 002us | mean: 0s 001ms 224us | max: 0s 121ms 405us | pstdev: 0s 006ms 041us
+Initiation to completion (517066 samples)
+  min: 0s 000ms 003us | mean: 0s 006ms 281us | max: 0s 096ms 731us | pstdev: 0s 011ms 939us
 
   Percentile  Count       Value          
-  0.5         180002      0s 000ms 473us 
-  0.75        270009      0s 000ms 560us 
-  0.8         288002      0s 000ms 589us 
-  0.9         324002      0s 000ms 770us 
-  0.95        342001      0s 001ms 390us 
-  0.990625    356625      0s 017ms 278us 
-  0.99902344  359648      0s 083ms 849us 
+  0.5         258539      0s 002ms 805us 
+  0.75        387802      0s 004ms 465us 
+  0.8         413664      0s 005ms 058us 
+  0.9         465360      0s 007ms 867us 
+  0.95        491214      0s 047ms 654us 
+  0.990625    512220      0s 055ms 760us 
+  0.99902344  516562      0s 065ms 097us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359722      3996.91
-benchmark.pool_overflow                 277         3.08
+benchmark.http_2xx                      516703      5741.11
+benchmark.pool_overflow                 363         4.03
 cluster_manager.cluster_added           4           0.04
 default.total_match_count               4           0.04
 membership_change                       4           0.04
 runtime.load_success                    1           0.01
 runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 123         1.37
-upstream_cx_rx_bytes_total              56476354    627514.75
-upstream_cx_total                       123         1.37
-upstream_cx_tx_bytes_total              15468089    171867.57
-upstream_rq_pending_overflow            277         3.08
-upstream_rq_pending_total               123         1.37
-upstream_rq_total                       359723      3996.92
-
-[14:42:23.965353][1][I] Done.
+upstream_cx_http1_total                 37          0.41
+upstream_cx_rx_bytes_total              81122371    901354.66
+upstream_cx_total                       37          0.41
+upstream_cx_tx_bytes_total              22218702    246873.09
+upstream_rq_pending_overflow            363         4.03
+upstream_rq_pending_total               37          0.41
+upstream_rq_total                       516714      5741.23
+
+[10:09:55.503051][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:10:00.503918][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:10:00.505088][1][I] Done.
 
 ```
 
@@ -593,102 +661,104 @@ upstream_rq_total                       359723      3996.92
 <summary>scale-down-httproutes-100</summary>
 
 ```plaintext
-[2024-06-25 14:42:41.429][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:42:41.430321][1][I] Detected 4 (v)CPUs with affinity..
-[14:42:41.430334][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:42:41.430336][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:42:41.430338][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:44:12.132884][18][I] Stopping after 89999 ms. Initiated: 90000 / Completed: 89996. (Completion rate was 999.9555777767906 per second.)
-[14:44:12.133405][21][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.999777777827 per second.)
-[14:44:12.133681][23][I] Stopping after 90000 ms. Initiated: 89995 / Completed: 89995. (Completion rate was 999.9439111410252 per second.)
-[14:44:12.138437][19][I] Stopping after 90005 ms. Initiated: 89979 / Completed: 89958. (Completion rate was 999.474453182769 per second.)
-[14:44:17.976650][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+Warning: 30 10:10:18.056][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[10:10:18.057130][1][I] Detected 4 (v)CPUs with affinity..
+[10:10:18.057143][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
+[10:10:18.057145][1][I] Global targets: 400 connections and 40000 calls per second.
+[10:10:18.057147][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[10:11:48.759104][18][I] Stopping after 90000 ms. Initiated: 209011 / Completed: 208988. (Completion rate was 2322.087186024952 per second.)
+[10:11:48.759212][21][I] Stopping after 90000 ms. Initiated: 49528 / Completed: 49526. (Completion rate was 550.2881062569155 per second.)
+[10:11:48.759225][19][I] Stopping after 90000 ms. Initiated: 82374 / Completed: 82369. (Completion rate was 915.2096671136363 per second.)
+[10:11:48.759235][22][I] Stopping after 90000 ms. Initiated: 83103 / Completed: 83098. (Completion rate was 923.3098082183817 per second.)
+[10:11:54.582462][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359649 samples)
-  min: 0s 000ms 297us | mean: 0s 009ms 493us | max: 0s 163ms 553us | pstdev: 0s 017ms 560us
+benchmark_http_client.latency_2xx (423617 samples)
+  min: 0s 000ms 341us | mean: 0s 007ms 208us | max: 0s 137ms 691us | pstdev: 0s 011ms 926us
 
   Percentile  Count       Value          
-  0.5         179826      0s 002ms 042us 
-  0.75        269740      0s 008ms 322us 
-  0.8         287721      0s 011ms 606us 
-  0.9         323685      0s 030ms 779us 
-  0.95        341667      0s 054ms 808us 
-  0.990625    356278      0s 079ms 679us 
-  0.99902344  359299      0s 106ms 098us 
+  0.5         211815      0s 003ms 194us 
+  0.75        317722      0s 006ms 279us 
+  0.8         338894      0s 007ms 606us 
+  0.9         381256      0s 016ms 511us 
+  0.95        402437      0s 035ms 002us 
+  0.990625    419646      0s 062ms 793us 
+  0.99902344  423204      0s 082ms 636us 
 
-Queueing and connection setup latency (359674 samples)
-  min: 0s 000ms 001us | mean: 0s 000ms 015us | max: 0s 033ms 947us | pstdev: 0s 000ms 269us
+Queueing and connection setup latency (423652 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 014us | max: 0s 035ms 192us | pstdev: 0s 000ms 210us
 
   Percentile  Count       Value          
-  0.5         179931      0s 000ms 008us 
-  0.75        269789      0s 000ms 010us 
-  0.8         287838      0s 000ms 011us 
-  0.9         323819      0s 000ms 011us 
-  0.95        341697      0s 000ms 015us 
-  0.990625    356303      0s 000ms 059us 
-  0.99902344  359323      0s 001ms 303us 
+  0.5         212529      0s 000ms 003us 
+  0.75        317890      0s 000ms 008us 
+  0.8         339187      0s 000ms 009us 
+  0.9         381367      0s 000ms 009us 
+  0.95        402534      0s 000ms 011us 
+  0.990625    419681      0s 000ms 121us 
+  0.99902344  423239      0s 001ms 867us 
 
-Request start to response end (359649 samples)
-  min: 0s 000ms 296us | mean: 0s 009ms 493us | max: 0s 163ms 553us | pstdev: 0s 017ms 560us
+Request start to response end (423617 samples)
+  min: 0s 000ms 341us | mean: 0s 007ms 207us | max: 0s 137ms 691us | pstdev: 0s 011ms 926us
 
   Percentile  Count       Value          
-  0.5         179829      0s 002ms 041us 
-  0.75        269740      0s 008ms 321us 
-  0.8         287722      0s 011ms 606us 
-  0.9         323687      0s 030ms 779us 
-  0.95        341667      0s 054ms 808us 
-  0.990625    356278      0s 079ms 679us 
-  0.99902344  359299      0s 106ms 098us 
+  0.5         211809      0s 003ms 194us 
+  0.75        317719      0s 006ms 279us 
+  0.8         338894      0s 007ms 606us 
+  0.9         381256      0s 016ms 510us 
+  0.95        402437      0s 035ms 002us 
+  0.990625    419646      0s 062ms 793us 
+  0.99902344  423204      0s 082ms 636us 
 
-Response body size in bytes (359649 samples)
+Response body size in bytes (423617 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359649 samples)
+Response header size in bytes (423617 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Blocking. Results are skewed when significant numbers are reported here. (19052 samples)
-  min: 0s 000ms 039us | mean: 0s 006ms 142us | max: 0s 146ms 767us | pstdev: 0s 012ms 746us
+Blocking. Results are skewed when significant numbers are reported here. (142751 samples)
+  min: 0s 000ms 035us | mean: 0s 002ms 521us | max: 0s 105ms 373us | pstdev: 0s 006ms 732us
 
   Percentile  Count       Value          
-  0.5         9526        0s 001ms 273us 
-  0.75        14289       0s 004ms 540us 
-  0.8         15242       0s 006ms 354us 
-  0.9         17147       0s 018ms 240us 
-  0.95        18100       0s 036ms 243us 
-  0.990625    18874       0s 063ms 096us 
-  0.99902344  19034       0s 087ms 937us 
+  0.5         71376       0s 000ms 888us 
+  0.75        107064      0s 001ms 861us 
+  0.8         114202      0s 002ms 248us 
+  0.9         128476      0s 004ms 006us 
+  0.95        135614      0s 008ms 008us 
+  0.990625    141413      0s 041ms 697us 
+  0.99902344  142612      0s 064ms 958us 
 
-Initiation to completion (359949 samples)
-  min: 0s 000ms 006us | mean: 0s 009ms 592us | max: 0s 163ms 594us | pstdev: 0s 017ms 643us
+Initiation to completion (423981 samples)
+  min: 0s 000ms 005us | mean: 0s 007ms 283us | max: 0s 137ms 756us | pstdev: 0s 011ms 948us
 
   Percentile  Count       Value          
-  0.5         179976      0s 002ms 093us 
-  0.75        269962      0s 008ms 477us 
-  0.8         287962      0s 011ms 824us 
-  0.9         323955      0s 030ms 991us 
-  0.95        341957      0s 055ms 142us 
-  0.990625    356578      0s 080ms 228us 
-  0.99902344  359598      0s 106ms 164us 
+  0.5         211995      0s 003ms 260us 
+  0.75        317989      0s 006ms 396us 
+  0.8         339189      0s 007ms 761us 
+  0.9         381583      0s 016ms 687us 
+  0.95        402787      0s 035ms 110us 
+  0.990625    420007      0s 062ms 932us 
+  0.99902344  423567      0s 082ms 649us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359649      3996.04
-benchmark.pool_overflow                 300         3.33
+benchmark.http_2xx                      423617      4706.85
+benchmark.pool_overflow                 364         4.04
 cluster_manager.cluster_added           4           0.04
 default.total_match_count               4           0.04
 membership_change                       4           0.04
 runtime.load_success                    1           0.01
 runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 100         1.11
-upstream_cx_rx_bytes_total              56464893    627378.34
-upstream_cx_total                       100         1.11
-upstream_cx_tx_bytes_total              15465939    171841.20
-upstream_rq_pending_overflow            300         3.33
-upstream_rq_pending_total               100         1.11
-upstream_rq_total                       359674      3996.32
-
-[14:44:22.981221][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
-[14:44:22.985214][1][I] Done.
+upstream_cx_http1_total                 36          0.40
+upstream_cx_rx_bytes_total              66507869    738975.37
+upstream_cx_total                       36          0.40
+upstream_cx_tx_bytes_total              18217036    202411.25
+upstream_rq_pending_overflow            364         4.04
+upstream_rq_pending_total               36          0.40
+upstream_rq_total                       423652      4707.24
+
+[10:11:59.584852][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:12:04.585643][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:12:09.586270][22][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:12:09.587436][1][I] Done.
 
 ```
 
@@ -698,120 +768,104 @@ upstream_rq_total                       359674      3996.32
 <summary>scale-down-httproutes-50</summary>
 
 ```plaintext
-[2024-06-25 14:44:35.399][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:44:35.400594][1][I] Detected 4 (v)CPUs with affinity..
-[14:44:35.400604][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:44:35.400607][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:44:35.400609][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:45:50.873708][19][E] Exiting due to failing termination predicate
-[14:45:50.873747][19][I] Stopping after 74767 ms. Initiated: 74767 / Completed: 74746. (Completion rate was 999.716774109537 per second.)
-[14:45:50.874918][18][E] Exiting due to failing termination predicate
-[14:45:50.875120][18][I] Stopping after 74769 ms. Initiated: 74770 / Completed: 74749. (Completion rate was 999.7209036132042 per second.)
-[14:45:50.878184][20][E] Exiting due to failing termination predicate
-[14:45:50.878203][20][I] Stopping after 74772 ms. Initiated: 74772 / Completed: 74750. (Completion rate was 999.6972288218956 per second.)
-[14:45:50.880264][21][E] Exiting due to failing termination predicate
-[14:45:50.880286][21][I] Stopping after 74773 ms. Initiated: 74774 / Completed: 74747. (Completion rate was 999.6424011911454 per second.)
-[14:45:51.840758][1][E] Terminated early because of a failure predicate.
-[14:45:51.840780][1][I] Check the output for problematic counter values. The default Nighthawk failure predicates report failure if (1) Nighthawk could not connect to the target (see 'benchmark.pool_connection_failure' counter; check the address and port number, and try explicitly setting --address-family v4 or v6, especially when using DNS; instead of localhost try 127.0.0.1 or ::1 explicitly), (2) the protocol was not supported by the target (see 'benchmark.stream_resets' counter; check http/https in the URI, --h2), (3) the target returned a 4xx or 5xx HTTP response code (see 'benchmark.http_4xx' and 'benchmark.http_5xx' counters; check the URI path and the server config), or (4) a custom gRPC RequestSource failed. --failure-predicate can be used to relax expectations.
-[14:45:56.841540][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+Warning: 29 03:03:53.663][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[03:03:53.664682][1][I] Detected 4 (v)CPUs with affinity..
+[03:03:53.664695][1][I] Starting 4 threads / event loops. Time limit: 30 seconds.
+[03:03:53.664698][1][I] Global targets: 400 connections and 40000 calls per second.
+[03:03:53.664700][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[03:04:24.367434][23][I] Stopping after 30000 ms. Initiated: 46577 / Completed: 46567. (Completion rate was 1552.2191046582072 per second.)
+[03:04:24.367829][18][I] Stopping after 30000 ms. Initiated: 42300 / Completed: 42290. (Completion rate was 1409.6315198541051 per second.)
+[03:04:24.368549][21][I] Stopping after 30001 ms. Initiated: 39600 / Completed: 39591. (Completion rate was 1319.637581142412 per second.)
+[03:04:24.367485][19][I] Stopping after 29994 ms. Initiated: 14551 / Completed: 14549. (Completion rate was 485.05192262626696 per second.)
+[03:04:30.226109][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (298738 samples)
-  min: 0s 000ms 307us | mean: 0s 011ms 515us | max: 0s 187ms 269us | pstdev: 0s 019ms 783us
-
-  Percentile  Count       Value          
-  0.5         149369      0s 002ms 416us 
-  0.75        224054      0s 011ms 230us 
-  0.8         238992      0s 016ms 571us 
-  0.9         268865      0s 041ms 666us 
-  0.95        283803      0s 059ms 402us 
-  0.990625    295939      0s 085ms 483us 
-  0.99902344  298447      0s 120ms 631us 
-
-benchmark_http_client.latency_5xx (7 samples)
-  min: 0s 000ms 210us | mean: 0s 000ms 884us | max: 0s 001ms 337us | pstdev: 0s 000ms 404us
+benchmark_http_client.latency_2xx (142634 samples)
+  min: 0s 000ms 350us | mean: 0s 007ms 306us | max: 0s 108ms 011us | pstdev: 0s 010ms 777us
 
   Percentile  Count       Value          
-  0.5         4           0s 000ms 683us 
-  0.75        6           0s 001ms 309us 
-  0.8         6           0s 001ms 309us 
+  0.5         71317       0s 003ms 525us 
+  0.75        106976      0s 006ms 682us 
+  0.8         114108      0s 008ms 188us 
+  0.9         128372      0s 019ms 436us 
+  0.95        135503      0s 031ms 845us 
+  0.990625    141297      0s 055ms 373us 
+  0.99902344  142495      0s 080ms 084us 
 
-Queueing and connection setup latency (298836 samples)
-  min: 0s 000ms 001us | mean: 0s 000ms 016us | max: 0s 075ms 845us | pstdev: 0s 000ms 315us
+Queueing and connection setup latency (142665 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 016us | max: 0s 030ms 452us | pstdev: 0s 000ms 301us
 
   Percentile  Count       Value          
-  0.5         149531      0s 000ms 008us 
-  0.75        224310      0s 000ms 010us 
-  0.8         239171      0s 000ms 010us 
-  0.9         268973      0s 000ms 011us 
-  0.95        283896      0s 000ms 016us 
-  0.990625    296035      0s 000ms 061us 
-  0.99902344  298545      0s 001ms 244us 
+  0.5         71653       0s 000ms 003us 
+  0.75        107071      0s 000ms 008us 
+  0.8         114147      0s 000ms 009us 
+  0.9         128437      0s 000ms 010us 
+  0.95        135540      0s 000ms 011us 
+  0.990625    141328      0s 000ms 076us 
+  0.99902344  142526      0s 002ms 365us 
 
-Request start to response end (298745 samples)
-  min: 0s 000ms 210us | mean: 0s 011ms 514us | max: 0s 187ms 269us | pstdev: 0s 019ms 783us
+Request start to response end (142634 samples)
+  min: 0s 000ms 350us | mean: 0s 007ms 305us | max: 0s 108ms 011us | pstdev: 0s 010ms 777us
 
   Percentile  Count       Value          
-  0.5         149373      0s 002ms 415us 
-  0.75        224059      0s 011ms 229us 
-  0.8         238996      0s 016ms 569us 
-  0.9         268871      0s 041ms 664us 
-  0.95        283810      0s 059ms 402us 
-  0.990625    295946      0s 085ms 483us 
-  0.99902344  298454      0s 120ms 631us 
+  0.5         71318       0s 003ms 525us 
+  0.75        106977      0s 006ms 681us 
+  0.8         114108      0s 008ms 187us 
+  0.9         128371      0s 019ms 434us 
+  0.95        135503      0s 031ms 842us 
+  0.990625    141297      0s 055ms 373us 
+  0.99902344  142495      0s 080ms 084us 
 
-Response body size in bytes (298745 samples)
-  min: 0 | mean: 9.999765686455003 | max: 10 | pstdev: 0.048405377254271256
+Response body size in bytes (142634 samples)
+  min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (298745 samples)
-  min: 58 | mean: 109.99878156956602 | max: 110 | pstdev: 0.25170796172221055
+Response header size in bytes (142634 samples)
+  min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Blocking. Results are skewed when significant numbers are reported here. (8534 samples)
-  min: 0s 000ms 040us | mean: 0s 006ms 742us | max: 0s 101ms 433us | pstdev: 0s 012ms 626us
+Blocking. Results are skewed when significant numbers are reported here. (42514 samples)
+  min: 0s 000ms 036us | mean: 0s 002ms 819us | max: 0s 097ms 796us | pstdev: 0s 006ms 582us
 
   Percentile  Count       Value          
-  0.5         4267        0s 001ms 369us 
-  0.75        6401        0s 005ms 750us 
-  0.8         6828        0s 008ms 406us 
-  0.9         7681        0s 022ms 739us 
-  0.95        8108        0s 037ms 554us 
-  0.990625    8454        0s 058ms 765us 
-  0.99902344  8526        0s 078ms 221us 
+  0.5         21257       0s 000ms 979us 
+  0.75        31886       0s 002ms 264us 
+  0.8         34012       0s 002ms 802us 
+  0.9         38263       0s 005ms 232us 
+  0.95        40389       0s 011ms 347us 
+  0.990625    42116       0s 036ms 845us 
+  0.99902344  42473       0s 061ms 714us 
 
-Initiation to completion (298992 samples)
-  min: 0s 000ms 005us | mean: 0s 011ms 618us | max: 0s 187ms 277us | pstdev: 0s 019ms 857us
+Initiation to completion (142997 samples)
+  min: 0s 000ms 003us | mean: 0s 007ms 382us | max: 0s 108ms 048us | pstdev: 0s 010ms 803us
 
   Percentile  Count       Value          
-  0.5         149496      0s 002ms 465us 
-  0.75        224244      0s 011ms 490us 
-  0.8         239195      0s 016ms 867us 
-  0.9         269093      0s 041ms 924us 
-  0.95        284043      0s 059ms 586us 
-  0.990625    296189      0s 085ms 766us 
-  0.99902344  298701      0s 120ms 954us 
+  0.5         71499       0s 003ms 591us 
+  0.75        107249      0s 006ms 808us 
+  0.8         114399      0s 008ms 328us 
+  0.9         128698      0s 019ms 615us 
+  0.95        135848      0s 031ms 933us 
+  0.990625    141657      0s 055ms 416us 
+  0.99902344  142858      0s 080ms 097us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      298738      3995.38
-benchmark.http_5xx                      7           0.09
-benchmark.pool_overflow                 247         3.30
-cluster_manager.cluster_added           4           0.05
-default.total_match_count               4           0.05
-membership_change                       4           0.05
-runtime.load_success                    1           0.01
-runtime.override_dir_not_exists         1           0.01
-sequencer.failed_terminations           4           0.05
-upstream_cx_http1_total                 153         2.05
-upstream_cx_rx_bytes_total              46902510    627283.31
-upstream_cx_total                       153         2.05
-upstream_cx_tx_bytes_total              12849948    171857.71
-upstream_rq_pending_overflow            247         3.30
-upstream_rq_pending_total               153         2.05
-upstream_rq_total                       298836      3996.69
-
-[14:46:01.842997][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
-[14:46:06.845068][20][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
-[14:46:11.847277][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
-[14:46:11.850206][1][E] An error occurred.
+benchmark.http_2xx                      142634      4754.58
+benchmark.pool_overflow                 363         12.10
+cluster_manager.cluster_added           4           0.13
+default.total_match_count               4           0.13
+membership_change                       4           0.13
+runtime.load_success                    1           0.03
+runtime.override_dir_not_exists         1           0.03
+upstream_cx_http1_total                 37          1.23
+upstream_cx_rx_bytes_total              22393538    746468.86
+upstream_cx_total                       37          1.23
+upstream_cx_tx_bytes_total              6134595     204491.32
+upstream_rq_pending_overflow            363         12.10
+upstream_rq_pending_total               37          1.23
+upstream_rq_total                       142665      4755.61
+
+[03:04:35.227368][19][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[03:04:40.228272][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[03:04:45.229345][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[03:04:45.231026][1][I] Done.
 
 ```
 
@@ -821,89 +875,102 @@ upstream_rq_total                       298836      3996.69
 <summary>scale-down-httproutes-10</summary>
 
 ```plaintext
-[2024-06-25 14:48:06.510][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
-[14:48:06.510881][1][I] Detected 4 (v)CPUs with affinity..
-[14:48:06.510893][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
-[14:48:06.510895][1][I] Global targets: 400 connections and 4000 calls per second.
-[14:48:06.510897][1][I]    (Per-worker targets: 100 connections and 1000 calls per second)
-[14:49:37.212970][19][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9998000000401 per second.)
-[14:49:37.213444][21][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9973000072899 per second.)
-[14:49:37.213541][23][I] Stopping after 90000 ms. Initiated: 90000 / Completed: 90000. (Completion rate was 999.9989777788228 per second.)
-[14:49:37.213971][18][I] Stopping after 90001 ms. Initiated: 89999 / Completed: 89996. (Completion rate was 999.9414452707166 per second.)
+Warning: 30 10:15:03.038][1][warning][misc] [external/envoy/source/common/protobuf/message_validator_impl.cc:21] Deprecated field: type envoy.config.core.v3.HeaderValueOption Using deprecated option 'envoy.config.core.v3.HeaderValueOption.append' from file base.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.
+[10:15:03.039299][1][I] Detected 4 (v)CPUs with affinity..
+[10:15:03.039310][1][I] Starting 4 threads / event loops. Time limit: 90 seconds.
+[10:15:03.039313][1][I] Global targets: 400 connections and 40000 calls per second.
+[10:15:03.039314][1][I]    (Per-worker targets: 100 connections and 10000 calls per second)
+[10:16:33.741189][23][I] Stopping after 90000 ms. Initiated: 258274 / Completed: 258258. (Completion rate was 2869.5316753816987 per second.)
+[10:16:33.741450][18][I] Stopping after 90000 ms. Initiated: 35338 / Completed: 35338. (Completion rate was 392.64273862987994 per second.)
+[10:16:33.741587][21][I] Stopping after 90000 ms. Initiated: 196085 / Completed: 196074. (Completion rate was 2178.588477687607 per second.)
+[10:16:33.742737][19][I] Stopping after 90001 ms. Initiated: 35313 / Completed: 35313. (Completion rate was 392.3594516123065 per second.)
+[10:16:39.388073][21][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
 Nighthawk - A layer 7 protocol benchmarking tool.
 
-benchmark_http_client.latency_2xx (359809 samples)
-  min: 0s 000ms 297us | mean: 0s 000ms 525us | max: 0s 048ms 130us | pstdev: 0s 000ms 466us
+benchmark_http_client.latency_2xx (524619 samples)
+  min: 0s 000ms 363us | mean: 0s 005ms 917us | max: 0s 093ms 347us | pstdev: 0s 011ms 507us
 
-[14:49:42.728878][18][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
   Percentile  Count       Value          
-  0.5         179925      0s 000ms 450us 
-  0.75        269871      0s 000ms 525us 
-  0.8         287855      0s 000ms 549us 
-  0.9         323830      0s 000ms 661us 
-  0.95        341819      0s 000ms 762us 
-  0.990625    356436      0s 001ms 585us 
-  0.99902344  359458      0s 007ms 084us 
+  0.5         262326      0s 002ms 779us 
+  0.75        393472      0s 004ms 063us 
+  0.8         419697      0s 004ms 496us 
+  0.9         472160      0s 006ms 384us 
+  0.95        498391      0s 046ms 964us 
+  0.990625    519704      0s 054ms 102us 
+  0.99902344  524107      0s 058ms 939us 
 
-Queueing and connection setup latency (359812 samples)
-  min: 0s 000ms 002us | mean: 0s 000ms 012us | max: 0s 034ms 091us | pstdev: 0s 000ms 067us
+Queueing and connection setup latency (524646 samples)
+  min: 0s 000ms 001us | mean: 0s 000ms 010us | max: 0s 019ms 046us | pstdev: 0s 000ms 096us
 
   Percentile  Count       Value          
-  0.5         180343      0s 000ms 010us 
-  0.75        269955      0s 000ms 011us 
-  0.8         288513      0s 000ms 011us 
-  0.9         323857      0s 000ms 012us 
-  0.95        341824      0s 000ms 023us 
-  0.990625    356439      0s 000ms 050us 
-  0.99902344  359461      0s 000ms 189us 
+  0.5         262650      0s 000ms 003us 
+  0.75        393534      0s 000ms 008us 
+  0.8         420137      0s 000ms 009us 
+  0.9         472311      0s 000ms 009us 
+  0.95        498511      0s 000ms 011us 
+  0.990625    519728      0s 000ms 076us 
+  0.99902344  524134      0s 001ms 276us 
 
-Request start to response end (359809 samples)
-  min: 0s 000ms 297us | mean: 0s 000ms 524us | max: 0s 048ms 130us | pstdev: 0s 000ms 466us
+Request start to response end (524619 samples)
+  min: 0s 000ms 363us | mean: 0s 005ms 917us | max: 0s 093ms 347us | pstdev: 0s 011ms 507us
 
   Percentile  Count       Value          
-  0.5         179906      0s 000ms 450us 
-  0.75        269861      0s 000ms 524us 
-  0.8         287864      0s 000ms 549us 
-  0.9         323829      0s 000ms 661us 
-  0.95        341820      0s 000ms 761us 
-  0.990625    356436      0s 001ms 585us 
-  0.99902344  359458      0s 007ms 083us 
+  0.5         262310      0s 002ms 778us 
+  0.75        393465      0s 004ms 062us 
+  0.8         419696      0s 004ms 496us 
+  0.9         472160      0s 006ms 384us 
+  0.95        498389      0s 046ms 962us 
+  0.990625    519707      0s 054ms 102us 
+  0.99902344  524107      0s 058ms 939us 
 
-Response body size in bytes (359809 samples)
+Response body size in bytes (524619 samples)
   min: 10 | mean: 10 | max: 10 | pstdev: 0
 
-Response header size in bytes (359809 samples)
+Response header size in bytes (524619 samples)
   min: 110 | mean: 110 | max: 110 | pstdev: 0
 
-Initiation to completion (359996 samples)
-  min: 0s 000ms 005us | mean: 0s 000ms 543us | max: 0s 048ms 146us | pstdev: 0s 000ms 476us
+Blocking. Results are skewed when significant numbers are reported here. (158918 samples)
+  min: 0s 000ms 034us | mean: 0s 002ms 264us | max: 0s 069ms 718us | pstdev: 0s 007ms 119us
+
+  Percentile  Count       Value          
+  0.5         79459       0s 000ms 812us 
+  0.75        119189      0s 001ms 826us 
+  0.8         127135      0s 002ms 141us 
+  0.9         143027      0s 003ms 136us 
+  0.95        150973      0s 004ms 425us 
+  0.990625    157429      0s 048ms 680us 
+  0.99902344  158763      0s 055ms 619us 
+
+Initiation to completion (524983 samples)
+  min: 0s 000ms 005us | mean: 0s 005ms 969us | max: 0s 093ms 364us | pstdev: 0s 011ms 505us
 
   Percentile  Count       Value          
-  0.5         179999      0s 000ms 468us 
-  0.75        269997      0s 000ms 543us 
-  0.8         288002      0s 000ms 568us 
-  0.9         324002      0s 000ms 683us 
-  0.95        341998      0s 000ms 783us 
-  0.990625    356622      0s 001ms 632us 
-  0.99902344  359645      0s 007ms 247us 
+  0.5         262493      0s 002ms 832us 
+  0.75        393739      0s 004ms 131us 
+  0.8         419987      0s 004ms 571us 
+  0.9         472485      0s 006ms 477us 
+  0.95        498740      0s 046ms 983us 
+  0.990625    520063      0s 054ms 147us 
+  0.99902344  524471      0s 059ms 058us 
 
 Counter                                 Value       Per second
-benchmark.http_2xx                      359809      3997.86
-benchmark.pool_overflow                 187         2.08
+benchmark.http_2xx                      524619      5829.06
+benchmark.pool_overflow                 364         4.04
 cluster_manager.cluster_added           4           0.04
 default.total_match_count               4           0.04
 membership_change                       4           0.04
 runtime.load_success                    1           0.01
 runtime.override_dir_not_exists         1           0.01
-upstream_cx_http1_total                 66          0.73
-upstream_cx_rx_bytes_total              56490013    627663.98
-upstream_cx_total                       66          0.73
-upstream_cx_tx_bytes_total              15471916    171909.40
-upstream_rq_pending_overflow            187         2.08
-upstream_rq_pending_total               66          0.73
-upstream_rq_total                       359812      3997.89
+upstream_cx_http1_total                 36          0.40
+upstream_cx_rx_bytes_total              82365183    915162.15
+upstream_cx_total                       36          0.40
+upstream_cx_tx_bytes_total              22559778    250662.41
+upstream_rq_pending_overflow            364         4.04
+upstream_rq_pending_total               36          0.40
+upstream_rq_total                       524646      5829.36
 
-[14:49:42.732798][1][I] Done.
+[10:16:44.389294][23][I] Wait for the connection pool drain timed out, proceeding to hard shutdown.
+[10:16:44.391101][1][I] Done.
 
 ```
 
@@ -911,15 +978,15 @@ upstream_rq_total                       359812      3997.89
 
 ### Metrics
 
-|Benchmark Name           |Envoy Gateway Memory (MiB)|Envoy Gateway Total CPU (Seconds)|Envoy Proxy Memory: k5s2s<sup>[1]</sup> (MiB)|
+|Benchmark Name           |Envoy Gateway Memory (MiB)|Envoy Gateway Total CPU (Seconds)|Envoy Proxy Memory: 4lvn5<sup>[1]</sup> (MiB)|
 |-                        |-                         |-                                |-                                            |
-|scale-up-httproutes-10   |76                        |0.34                             |7                                            |
-|scale-up-httproutes-50   |114                       |1.94                             |12                                           |
-|scale-up-httproutes-100  |195                       |10.85                            |20                                           |
-|scale-up-httproutes-300  |1124                      |176.36                           |81                                           |
-|scale-up-httproutes-500  |1588                      |16.69                            |190                                          |
-|scale-down-httproutes-300|661                       |6.04                             |87                                           |
-|scale-down-httproutes-100|679                       |104.73                           |95                                           |
-|scale-down-httproutes-50 |143                       |172.84                           |53                                           |
-|scale-down-httproutes-10 |118                       |174.16                           |18                                           |
-1. envoy-gateway-system/envoy-benchmark-test-benchmark-0520098c-7668c94dd5-k5s2s
+|scale-up-httproutes-10   |78                        |0.39                             |7                                            |
+|scale-up-httproutes-50   |87                        |1.87                             |11                                           |
+|scale-up-httproutes-100  |167                       |8.9                              |20                                           |
+|scale-up-httproutes-300  |673                       |167.86                           |81                                           |
+|scale-up-httproutes-500  |1358                      |10.98                            |190                                          |
+|scale-down-httproutes-300|643                       |5.59                             |84                                           |
+|scale-down-httproutes-100|455                       |112.24                           |55                                           |
+|scale-down-httproutes-50 |147                       |150.17                           |20                                           |
+|scale-down-httproutes-10 |120                       |151.69                           |12                                           |
+1. envoy-gateway-system/envoy-benchmark-test-benchmark-0520098c-dbf5d95fb-4lvn5
diff --git a/test/benchmark/suite/render.go b/test/benchmark/suite/render.go
index e3c059685..44485b88b 100644
--- a/test/benchmark/suite/render.go
+++ b/test/benchmark/suite/render.go
@@ -110,7 +110,7 @@ func newMarkdownStyleTableWriter(writer io.Writer) *tabwriter.Writer {
 }
 
 func renderEnvSettingsTable(writer io.Writer) {
-	_, _ = fmt.Fprintln(writer, "Benchmark test settings:", "\n")
+	_, _ = fmt.Fprintln(writer, "Benchmark test settings:")
 
 	table := newMarkdownStyleTableWriter(writer)
 
@@ -144,7 +144,7 @@ func renderEnvSettingsTable(writer io.Writer) {
 	renderMetricsTableHeader(table, headers)
 
 	writeTableRow(table, headers, func(_ int, h ReportTableHeader) string {
-		env := strings.Replace(strings.ToUpper(h.Name), " ", "_", -1)
+		env := strings.ReplaceAll(strings.ToUpper(h.Name), " ", "_")
 		if v, ok := os.LookupEnv(benchmarkEnvPrefix + env); ok {
 			return v
 		}
@@ -260,13 +260,15 @@ func writeSection(writer io.Writer, title string, level int, content string) {
 
 // writeCollapsibleSection writes one collapsible section in Markdown style.
 func writeCollapsibleSection(writer io.Writer, title string, content []byte) {
-	_, _ = fmt.Fprintln(writer, fmt.Sprintf(`
+	summary := fmt.Sprintf("```plaintext\n%s\n```", content)
+	_, _ = fmt.Fprintf(writer, `
 <details>
 <summary>%s</summary>
 
 %s
 
-</details>`, title, fmt.Sprintf("```plaintext\n%s\n```", content)))
+</details>
+`, title, summary)
 }
 
 // writeTableRow writes one row in Markdown table style.
diff --git a/test/benchmark/suite/report.go b/test/benchmark/suite/report.go
index 949fb5fa8..c37539f62 100644
--- a/test/benchmark/suite/report.go
+++ b/test/benchmark/suite/report.go
@@ -81,6 +81,9 @@ func (r *BenchmarkReport) Collect(t *testing.T, ctx context.Context, job *types.
 
 func (r *BenchmarkReport) GetBenchmarkResult(t *testing.T, ctx context.Context, job *types.NamespacedName) error {
 	pods, err := r.kubeClient.Kube().CoreV1().Pods(job.Namespace).List(ctx, metav1.ListOptions{LabelSelector: "job-name=" + job.Name})
+	if err != nil {
+		return err
+	}
 
 	if len(pods.Items) < 1 {
 		return fmt.Errorf("failed to get any pods for job %s", job.String())
@@ -183,26 +186,28 @@ func (r *BenchmarkReport) getLogsFromPod(ctx context.Context, pod *types.Namespa
 func (r *BenchmarkReport) getMetricsFromPortForwarder(t *testing.T, pod *types.NamespacedName, url string) ([]byte, error) {
 	fw, err := kube.NewLocalPortForwarder(r.kubeClient, *pod, localMetricsPort, controlPlaneMetricsPort)
 	if err != nil {
-		return nil, fmt.Errorf("failed to build port forwarder for pod %s: %v", pod.String(), err)
+		return nil, fmt.Errorf("failed to build port forwarder for pod %s: %w", pod.String(), err)
 	}
 
 	if err = fw.Start(); err != nil {
 		fw.Stop()
 
-		return nil, fmt.Errorf("failed to start port forwarder for pod %s: %v", pod.String(), err)
+		return nil, fmt.Errorf("failed to start port forwarder for pod %s: %w", pod.String(), err)
 	}
+	requestURL := fmt.Sprintf("http://%s%s", fw.Address(), url)
 
 	var out []byte
 	// Retrieving metrics from Pod.
-	go func() {
+	go func(requestURL string) {
 		defer fw.Stop()
 
-		url := fmt.Sprintf("http://%s%s", fw.Address(), url)
-		resp, err := http.Get(url)
+		//nolint: gosec
+		resp, err := http.Get(requestURL)
 		if err != nil {
-			t.Errorf("failed to request %s: %v", url, err)
+			t.Errorf("failed to request %s: %v", requestURL, err)
 			return
 		}
+		defer resp.Body.Close()
 
 		metrics, err := io.ReadAll(resp.Body)
 		if err != nil {
@@ -211,7 +216,7 @@ func (r *BenchmarkReport) getMetricsFromPortForwarder(t *testing.T, pod *types.N
 		}
 
 		out = metrics
-	}()
+	}(requestURL)
 
 	fw.WaitForStop()
 
diff --git a/test/benchmark/suite/suite.go b/test/benchmark/suite/suite.go
index 919e019e6..376766ae1 100644
--- a/test/benchmark/suite/suite.go
+++ b/test/benchmark/suite/suite.go
@@ -50,7 +50,8 @@ type BenchmarkTestSuite struct {
 }
 
 func NewBenchmarkTestSuite(client client.Client, options BenchmarkOptions,
-	gatewayManifest, httpRouteManifest, benchmarkClientManifest, reportPath string) (*BenchmarkTestSuite, error) {
+	gatewayManifest, httpRouteManifest, benchmarkClientManifest, reportPath string,
+) (*BenchmarkTestSuite, error) {
 	var (
 		gateway         = new(gwapiv1.Gateway)
 		httproute       = new(gwapiv1.HTTPRoute)
@@ -132,13 +133,13 @@ func (b *BenchmarkTestSuite) Run(t *testing.T, tests []BenchmarkTest) {
 	}
 
 	if len(b.ReportSavePath) > 0 {
-		if err := os.WriteFile(b.ReportSavePath, writer.Bytes(), 0644); err != nil {
+		if err := os.WriteFile(b.ReportSavePath, writer.Bytes(), 0o600); err != nil {
 			t.Errorf("Error writing report to path '%s': %v", b.ReportSavePath, err)
 		} else {
 			t.Logf("Writing report to path '%s' successfully", b.ReportSavePath)
 		}
 	} else {
-		t.Log(fmt.Sprintf("%s", writer.Bytes()))
+		t.Logf("%s", writer.Bytes())
 	}
 }
 
diff --git a/test/benchmark/tests/scale_httproutes.go b/test/benchmark/tests/scale_httproutes.go
index ca9c13f18..169a3faeb 100644
--- a/test/benchmark/tests/scale_httproutes.go
+++ b/test/benchmark/tests/scale_httproutes.go
@@ -78,7 +78,7 @@ var ScaleHTTPRoutes = suite.BenchmarkTest{
 		})
 
 		t.Run("scaling down httproutes", func(t *testing.T) {
-			var start = routeScales[routeScalesN-1]
+			start := routeScales[routeScalesN-1]
 
 			for i := routeScalesN - 2; i >= 0; i-- {
 				scale := routeScales[i]
@@ -89,8 +89,7 @@ var ScaleHTTPRoutes = suite.BenchmarkTest{
 						routeNNs = routeNNs[:len(routeNNs)-1]
 
 						// Making sure we are deleting the right one route.
-						require.Equal(t, routeNN,
-							types.NamespacedName{Name: route.Name, Namespace: route.Namespace})
+						require.Equal(t, types.NamespacedName{Name: route.Name, Namespace: route.Namespace}, routeNN)
 
 						t.Logf("Delete HTTPRoute: %s", routeNN.String())
 					})
diff --git a/test/config/gatewayclass.yaml b/test/config/gatewayclass.yaml
index 8fc6806b0..4c1241a7b 100644
--- a/test/config/gatewayclass.yaml
+++ b/test/config/gatewayclass.yaml
@@ -79,6 +79,10 @@ spec:
             namespace: monitoring
             port: 4317
       customTags:
+        "provider":
+          type: Literal
+          literal:
+            value: "otel"
         "k8s.cluster.name":
           type: Literal
           literal:
@@ -165,4 +169,3 @@ metadata:
 spec:
   controllerName: gateway.envoyproxy.io/gatewayclass-controller
 ---
-
diff --git a/test/e2e/base/manifests.yaml b/test/e2e/base/manifests.yaml
index ded6c648a..076240d60 100644
--- a/test/e2e/base/manifests.yaml
+++ b/test/e2e/base/manifests.yaml
@@ -43,6 +43,12 @@ spec:
     allowedRoutes:
       namespaces:
         from: All
+  infrastructure:
+    parametersRef:
+      group: gateway.envoyproxy.io
+      kind: EnvoyProxy
+      name: zipkin-tracing
+      namespace: envoy-gateway-system
 ---
 apiVersion: gateway.networking.k8s.io/v1
 kind: Gateway
@@ -1092,9 +1098,74 @@ spec:
   ports:
   - name: grpc-als
     protocol: TCP
+    appProtocol: grpc
     port: 8080
     targetPort: 8080
   - name: http-monitoring
     protocol: TCP
     port: 19001
     targetPort: 19001
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: Gateway
+metadata:
+  name: eg-special-case
+  namespace: gateway-conformance-infra
+spec:
+  gatewayClassName: "{GATEWAY_CLASS_NAME}"
+  listeners:
+  - name: http
+    port: 80
+    protocol: HTTP
+    allowedRoutes:
+      namespaces:
+        from: All
+  infrastructure:
+    parametersRef:
+      group: gateway.envoyproxy.io
+      kind: EnvoyProxy
+      name: zipkin-tracing
+---
+#  This is a EnvoyProxy used for Zipkin tracing and will
+#  target to the eg-special-case Gateway
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: zipkin-tracing
+  namespace: gateway-conformance-infra
+spec:
+  logging:
+    level:
+      default: debug
+  telemetry:
+    tracing:
+      provider:
+        type: Zipkin
+        backendRefs:
+        - name: otel-collector
+          namespace: monitoring
+          port: 9411
+        zipkin:
+          enable128BitTraceId: true
+      customTags:
+        "provider":
+          type: Literal
+          literal:
+            value: "zipkin"
+        "k8s.cluster.name":
+          type: Literal
+          literal:
+            value: "envoy-gateway"
+        "k8s.pod.name":
+          type: Environment
+          environment:
+            name: ENVOY_POD_NAME
+            defaultValue: "-"
+        "k8s.namespace.name":
+          type: Environment
+          environment:
+            name: ENVOY_GATEWAY_NAMESPACE
+            defaultValue: "envoy-gateway-system"
+  shutdown:
+    drainTimeout: 5s
+    minDrainDuration: 1s
diff --git a/test/e2e/testdata/backend-health-check-active-http.yaml b/test/e2e/testdata/backend-health-check-active-http.yaml
new file mode 100644
index 000000000..999029c9d
--- /dev/null
+++ b/test/e2e/testdata/backend-health-check-active-http.yaml
@@ -0,0 +1,110 @@
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: health-check-active-http-pass-btp
+  namespace: gateway-conformance-infra
+spec:
+  targetRefs:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: http-with-health-check-active-http-pass
+      namespace: gateway-conformance-infra
+  healthCheck:
+    active:
+      timeout: 3s
+      interval: 5s
+      unhealthyThreshold: 3
+      healthyThreshold: 1
+      type: HTTP
+      http:
+        path: "/status/200"
+        expectedStatuses:
+          - 200
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: health-check-active-http-fail-btp
+  namespace: gateway-conformance-infra
+spec:
+  targetRefs:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: http-with-health-check-active-http-fail
+      namespace: gateway-conformance-infra
+  healthCheck:
+    active:
+      timeout: 3s
+      interval: 5s
+      unhealthyThreshold: 3
+      healthyThreshold: 1
+      type: HTTP
+      http:
+        path: "/status/418"
+        expectedStatuses:
+          - 200
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: http-with-health-check-active-http-pass
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: same-namespace
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /health-check-active-http-pass
+      backendRefs:
+        - name: infra-backend-v1
+          port: 8080
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: http-with-health-check-active-http-fail
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: same-namespace
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /health-check-active-http-fail
+      backendRefs:
+        - name: infra-backend-v1
+          port: 8080
+---
+# cluster panic threshold should be set to 0.0 to disable panic, to check whether health check works.
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyPatchPolicy
+metadata:
+  name: disable-cluster-panic-patch-policy
+  namespace: gateway-conformance-infra
+spec:
+  targetRef:
+    group: gateway.networking.k8s.io
+    kind: Gateway
+    name: same-namespace
+    namespace: gateway-conformance-infra
+  type: JSONPatch
+  jsonPatches:
+    - type: "type.googleapis.com/envoy.config.cluster.v3.Cluster"
+      name: "httproute/gateway-conformance-infra/http-with-health-check-active-http-pass/rule/0"
+      operation:
+        op: add
+        path: "/common_lb_config"
+        value:
+          healthy_panic_threshold:
+            value: 0.0
+    - type: "type.googleapis.com/envoy.config.cluster.v3.Cluster"
+      name: "httproute/gateway-conformance-infra/http-with-health-check-active-http-fail/rule/0"
+      operation:
+        op: add
+        path: "/common_lb_config"
+        value:
+          healthy_panic_threshold:
+            value: 0.0
diff --git a/test/e2e/testdata/tracing-otel.yaml b/test/e2e/testdata/tracing-otel.yaml
index f5b896a91..4c0aea806 100644
--- a/test/e2e/testdata/tracing-otel.yaml
+++ b/test/e2e/testdata/tracing-otel.yaml
@@ -10,7 +10,7 @@ spec:
     - matches:
         - path:
             type: PathPrefix
-            value: /tracing
+            value: /otel
       backendRefs:
         - name: infra-backend-v1
           port: 8080
diff --git a/test/e2e/testdata/tracing-zipkin.yaml b/test/e2e/testdata/tracing-zipkin.yaml
new file mode 100644
index 000000000..8cb2e10c1
--- /dev/null
+++ b/test/e2e/testdata/tracing-zipkin.yaml
@@ -0,0 +1,16 @@
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: tracing-zipkin
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: eg-special-case
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /zipkin
+      backendRefs:
+        - name: infra-backend-v2
+          port: 8080
diff --git a/test/e2e/tests/backend_health_check.go b/test/e2e/tests/backend_health_check.go
new file mode 100644
index 000000000..b8a384c69
--- /dev/null
+++ b/test/e2e/tests/backend_health_check.go
@@ -0,0 +1,142 @@
+// 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
+// +build e2e
+
+package tests
+
+import (
+	"fmt"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/require"
+	"k8s.io/apimachinery/pkg/types"
+	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
+	gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
+	"sigs.k8s.io/gateway-api/conformance/utils/http"
+	"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
+	"sigs.k8s.io/gateway-api/conformance/utils/suite"
+
+	"github.com/envoyproxy/gateway/internal/gatewayapi"
+	"github.com/envoyproxy/gateway/test/e2e/utils/prometheus"
+)
+
+func init() {
+	ConformanceTests = append(ConformanceTests, BackendHealthCheckActiveHTTPTest)
+}
+
+var BackendHealthCheckActiveHTTPTest = suite.ConformanceTest{
+	ShortName:   "BackendHealthCheckActiveHTTP",
+	Description: "Resource with BackendHealthCheckActiveHTTP enabled",
+	Manifests:   []string{"testdata/backend-health-check-active-http.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		t.Run("active http", func(t *testing.T) {
+			ns := "gateway-conformance-infra"
+			passRouteNN := types.NamespacedName{Name: "http-with-health-check-active-http-pass", Namespace: ns}
+			failRouteNN := types.NamespacedName{Name: "http-with-health-check-active-http-fail", Namespace: ns}
+			gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
+			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), passRouteNN, failRouteNN)
+
+			ancestorRef := gwapiv1a2.ParentReference{
+				Group:     gatewayapi.GroupPtr(gwapiv1.GroupName),
+				Kind:      gatewayapi.KindPtr(gatewayapi.KindGateway),
+				Namespace: gatewayapi.NamespacePtr(gwNN.Namespace),
+				Name:      gwapiv1.ObjectName(gwNN.Name),
+			}
+			BackendTrafficPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "health-check-active-http-pass-btp", Namespace: ns}, suite.ControllerName, ancestorRef)
+			BackendTrafficPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "health-check-active-http-fail-btp", Namespace: ns}, suite.ControllerName, ancestorRef)
+
+			promAddr, err := prometheus.Address(suite.Client,
+				types.NamespacedName{Name: "prometheus", Namespace: "monitoring"},
+			)
+			require.NoError(t, err)
+
+			passClusterName := fmt.Sprintf("httproute/%s/%s/rule/0", ns, passRouteNN.Name)
+			failClusterName := fmt.Sprintf("httproute/%s/%s/rule/0", ns, failRouteNN.Name)
+			gtwName := "same-namespace"
+
+			// health check requests will be distributed to the cluster with configured path.
+			// we can use membership_healthy stats to check whether health check works as expected.
+			passPromQL := fmt.Sprintf(`envoy_cluster_health_check_success{envoy_cluster_name="%s",gateway_envoyproxy_io_owning_gateway_name="%s"}`, passClusterName, gtwName)
+			failPromQL := fmt.Sprintf(`envoy_cluster_health_check_failure{envoy_cluster_name="%s",gateway_envoyproxy_io_owning_gateway_name="%s"}`, failClusterName, gtwName)
+
+			http.AwaitConvergence(
+				t,
+				suite.TimeoutConfig.RequiredConsecutiveSuccesses,
+				suite.TimeoutConfig.MaxTimeToConsistency,
+				func(_ time.Duration) bool {
+					// check membership_healthy stats from Prometheus
+					v, err := prometheus.QuerySum(promAddr, passPromQL)
+					if err != nil {
+						// wait until Prometheus sync stats
+						return false
+					}
+					t.Logf("cluster pass health check: success stats query count: %v", v)
+
+					if v == 0 {
+						t.Error("success is not the same as expected")
+					} else {
+						t.Log("success is the same as expected")
+					}
+
+					return true
+				},
+			)
+
+			http.AwaitConvergence(
+				t,
+				suite.TimeoutConfig.RequiredConsecutiveSuccesses,
+				suite.TimeoutConfig.MaxTimeToConsistency,
+				func(_ time.Duration) bool {
+					// check membership_healthy stats from Prometheus
+					v, err := prometheus.QuerySum(promAddr, failPromQL)
+					if err != nil {
+						// wait until Prometheus sync stats
+						return false
+					}
+					t.Logf("cluster fail health check: failure stats query count: %v", v)
+
+					if v == 0 {
+						t.Error("failure is not same as expected")
+					} else {
+						t.Log("failure is same as expected")
+					}
+
+					return true
+				},
+			)
+
+			t.Run("health check pass", func(t *testing.T) {
+				expectedResponse := http.ExpectedResponse{
+					Request: http.Request{
+						Path: "/health-check-active-http-pass",
+					},
+					Response: http.Response{
+						StatusCode: 200,
+					},
+					Namespace: ns,
+				}
+
+				http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+			})
+
+			t.Run("health check fail", func(t *testing.T) {
+				expectedResponse := http.ExpectedResponse{
+					Request: http.Request{
+						Path: "/health-check-active-http-fail",
+					},
+					Response: http.Response{
+						StatusCode: 503,
+					},
+					Namespace: ns,
+				}
+
+				http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+			})
+		})
+	},
+}
diff --git a/test/e2e/tests/tracing.go b/test/e2e/tests/tracing.go
index 9ded2662c..2fe6b4484 100644
--- a/test/e2e/tests/tracing.go
+++ b/test/e2e/tests/tracing.go
@@ -33,7 +33,7 @@ import (
 )
 
 func init() {
-	ConformanceTests = append(ConformanceTests, OpenTelemetryTracingTest)
+	ConformanceTests = append(ConformanceTests, OpenTelemetryTracingTest, ZipkinTracingTest)
 }
 
 var OpenTelemetryTracingTest = suite.ConformanceTest{
@@ -49,7 +49,7 @@ var OpenTelemetryTracingTest = suite.ConformanceTest{
 
 			expectedResponse := httputils.ExpectedResponse{
 				Request: httputils.Request{
-					Path: "/tracing",
+					Path: "/otel",
 				},
 				Response: httputils.Response{
 					StatusCode: 200,
@@ -61,6 +61,7 @@ var OpenTelemetryTracingTest = suite.ConformanceTest{
 
 			tags := map[string]string{
 				"component":    "proxy",
+				"provider":     "otel",
 				"service.name": naming.ServiceName(gwNN),
 			}
 			// let's wait for the log to be sent to stdout
@@ -83,6 +84,56 @@ var OpenTelemetryTracingTest = suite.ConformanceTest{
 	},
 }
 
+var ZipkinTracingTest = suite.ConformanceTest{
+	ShortName:   "ZipkinTracing",
+	Description: "Make sure Zipkin tracing is working",
+	Manifests:   []string{"testdata/tracing-zipkin.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		t.Run("tempo", func(t *testing.T) {
+			ns := "gateway-conformance-infra"
+			routeNN := types.NamespacedName{Name: "tracing-zipkin", Namespace: ns}
+			gwNN := types.NamespacedName{Name: "eg-special-case", Namespace: ns}
+			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+			expectedResponse := httputils.ExpectedResponse{
+				Request: httputils.Request{
+					Path: "/zipkin",
+				},
+				Response: httputils.Response{
+					StatusCode: 200,
+				},
+				Namespace: ns,
+			}
+			// make sure listener is ready
+			httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+
+			tags := map[string]string{
+				"component": "proxy",
+				"provider":  "zipkin",
+				// TODO: this came from --service-cluster, which is different from OTel,
+				// should make them kept consistent
+				"service.name": fmt.Sprintf("%s/%s", gwNN.Namespace, gwNN.Name),
+			}
+			// let's wait for the log to be sent to stdout
+			if err := wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, true,
+				func(ctx context.Context) (bool, error) {
+					count, err := QueryTraceFromTempo(t, suite.Client, tags)
+					if err != nil {
+						t.Logf("failed to get trace count from tempo: %v", err)
+						return false, nil
+					}
+
+					if count > 0 {
+						return true, nil
+					}
+					return false, nil
+				}); err != nil {
+				t.Errorf("failed to get trace from tempo: %v", err)
+			}
+		})
+	},
+}
+
 // QueryTraceFromTempo queries span count from tempo
 // TODO: move to utils package if needed
 func QueryTraceFromTempo(t *testing.T, c client.Client, tags map[string]string) (int, error) {
diff --git a/test/helm/gateway-addons-helm/e2e.out.yaml b/test/helm/gateway-addons-helm/e2e.out.yaml
index e53828af9..6154b656e 100644
--- a/test/helm/gateway-addons-helm/e2e.out.yaml
+++ b/test/helm/gateway-addons-helm/e2e.out.yaml
@@ -305,6 +305,7 @@ data:
           - batch
           receivers:
           - otlp
+          - zipkin
       telemetry:
         metrics:
           address: ${env:MY_POD_IP}:8888
@@ -9956,7 +9957,7 @@ spec:
   template:
     metadata:
       annotations:
-        checksum/config: 077be33cb293f9c37d065397da8156bf9f33a42ad56a3d5876f39de72c874023
+        checksum/config: 4eb06aca6ff4da4de927cb9ba7d8ceb883d2484011fbd670683037b8ea4d996c
         
       labels:
         app.kubernetes.io/name: opentelemetry-collector