Repository: envoyproxy/gateway
Pull request #4107 (2024-08-26 04:36:00)

build(deps): bump github.com/prometheus/client_golang from 1.20.0 to 1.20.2
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.0 to 1.20.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/prometheus/client_golang/releases">github.com/prometheus/client_golang's releases</a>.</em></p>
<blockquote>
<h2>v1.20.2</h2>
<ul>
<li>[BUGFIX] promhttp: Unset Content-Encoding header when data is uncompressed. <a href="https://redirect.github.com/prometheus/client_golang/issues/1596">#1596</a></li>
</ul>
<h2>v1.20.1</h2>
<p>This release contains the critical fix for the <a href="https://redirect.github.com/prometheus/client_golang/issues/1584">issue</a>. Thanks to <a href="https://github.com/geberl"><code>@​geberl</code></a>, <a href="https://github.com/CubicrootXYZ"><code>@​CubicrootXYZ</code></a>, <a href="https://github.com/zetaab"><code>@​zetaab</code></a> and <a href="https://github.com/timofurrer"><code>@​timofurrer</code></a> for helping us with the investigation!</p>
<ul>
<li>[BUGFIX] process-collector: Fixed unregistered descriptor error when using process collector with PedanticRegistry on Linux machines. <a href="https://redirect.github.com/prometheus/client_golang/issues/1587">#1587</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md">github.com/prometheus/client_golang's changelog</a>.</em></p>
<blockquote>
<h2>1.20.2 / 2024-08-23</h2>
<ul>
<li>[BUGFIX] promhttp: Unset Content-Encoding header when data is uncompressed. <a href="https://redirect.github.com/prometheus/client_golang/issues/1596">#1596</a></li>
</ul>
<h2>1.20.1 / 2024-08-20</h2>
<ul>
<li>[BUGFIX] process-collector: Fixed unregistered descriptor error when using process collector with <code>PedanticRegistry</code> on linux machines. <a href="https://redirect.github.com/prometheus/client_golang/issues/1587">#1587</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/prometheus/client_golang/commit/67121dc55a7c1ac353141e360a2b184c5e3d5529"><code>67121dc</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/client_golang/issues/1596">#1596</a> from mrueg/fix-uncompressed-content-header</li>
<li><a href="https://github.com/prometheus/client_golang/commit/187acd4ca1a05e3207990e427cae7057a1e58961"><code>187acd4</code></a> Cut 1.20.2</li>
<li><a href="https://github.com/prometheus/client_golang/commit/f7f8f3a1e2c09da4b88b78b7e04a9252187cf71f"><code>f7f8f3a</code></a> fix: Unset Content-Encoding header when uncompressed</li>
<li><a href="https://github.com/prometheus/client_golang/commit/2254d6c3087d3660f73785ae123c7cc705f2a9c2"><code>2254d6c</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/client_golang/issues/1587">#1587</a> from prometheus/fix-processcollector</li>
<li><a href="https://github.com/prometheus/client_golang/commit/4a15d0584653a36547195042512218cad99888c6"><code>4a15d05</code></a> Cut 1.20.1</li>
<li><a href="https://github.com/prometheus/client_golang/commit/f2dd7b35fd3f28b6a59b64953aab727b5c0c0404"><code>f2dd7b3</code></a> Use pedantic registry in other places too, to double check.</li>
<li><a href="https://github.com/prometheus/client_golang/commit/261fe84cd4f670b8e51bf74f6f6bbb96aa1fce20"><code>261fe84</code></a> bugfix: Pass network metrics to processCollector's Describe() function</li>
<li><a href="https://github.com/prometheus/client_golang/commit/5bf3341b6684a18bfdc019c9b2c154ab6a42c0a1"><code>5bf3341</code></a> Use NewPedanticRegistry in Process' Collector tests</li>
<li>See full diff in <a href="https://github.com/prometheus/client_golang/compare/v1.20.0...v1.20.2">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/prometheus/client_golang&package-manager=go_modules&previous-version=1.20.0&new-version=1.20.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/4107?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 67.91%. Comparing base [(`8ae9b09`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/8ae9b09398c692fb9af36f61e1289f2c81f80dbc?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`8c0f56f`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/8c0f56f4581c6442ee53ae4e5023481a9059db7a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #4107      +/-   ##
==========================================
- Coverage   67.97%   67.91%   -0.06%     
==========================================
  Files         187      187              
  Lines       23032    23032              
==========================================
- Hits        15656    15643      -13     
- Misses       6261     6271      +10     
- Partials     1115     1118       +3     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/4107?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).


Patch:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 7da0055d2..bc4bb1b15 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -19,7 +19,7 @@ jobs:
       - uses: ./tools/github-actions/setup-deps
 
       - name: Setup Graphviz
-        uses: ts-graphviz/setup-graphviz@v2
+        uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c  # v2.0.2
 
       # Benchmark
       - name: Run Benchmark tests
@@ -39,7 +39,7 @@ jobs:
         run: cd test/benchmark && zip -r benchmark_report.zip benchmark_report
 
       - name: Upload Benchmark Report
-        uses: actions/upload-artifact@v4  # version is better be consistent with actions/download-artifact
+        uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a  # v4.3.6
         with:
           name: benchmark_report
           path: test/benchmark/benchmark_report.zip
@@ -75,7 +75,7 @@ jobs:
         run: IMAGE_PULL_POLICY=IfNotPresent OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=${{ env.release_tag }} IMAGE=docker.io/envoyproxy/gateway TAG=${{ env.release_tag }} make helm-package helm-push
 
       - name: Download Benchmark Report
-        uses: actions/download-artifact@v4
+        uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16  # v4.1.8
         with:
           name: benchmark_report
           path: release-artifacts
diff --git a/api/v1alpha1/backend_types.go b/api/v1alpha1/backend_types.go
index 9e28a341c..6a039a5b4 100644
--- a/api/v1alpha1/backend_types.go
+++ b/api/v1alpha1/backend_types.go
@@ -123,6 +123,16 @@ type BackendSpec struct {
 	//
 	// +optional
 	AppProtocols []AppProtocolType `json:"appProtocols,omitempty"`
+
+	// Failover indicates whether the backend is designated as a failover.
+	// It is highly recommended to configure active or passive health checks to ensure that failover can be detected
+	// when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
+	// The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when
+	// the health of the active backends falls below 72%.
+	//
+	// +optional
+	// +notImplementedHide
+	Failover *bool `json:"failover,omitempty"`
 }
 
 // BackendConditionType is a type of condition for a backend. This type should be
diff --git a/api/v1alpha1/ext_auth_types.go b/api/v1alpha1/ext_auth_types.go
index 2ecb8674a..2d49a9df3 100644
--- a/api/v1alpha1/ext_auth_types.go
+++ b/api/v1alpha1/ext_auth_types.go
@@ -49,7 +49,6 @@ type ExtAuth struct {
 // https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto
 // +kubebuilder:validation:XValidation:message="backendRef or backendRefs needs to be set",rule="has(self.backendRef) || self.backendRefs.size() > 0"
 // +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)"
-// +kubebuilder:validation:XValidation:message="Exactly one backendRef can be specified in backendRefs.",rule="has(self.backendRefs) && self.backendRefs.size()==1"
 // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service' || f.kind == 'Backend') : true"
 // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\" || f.group == 'gateway.envoyproxy.io')) : true"
 type GRPCExtAuthService struct {
@@ -61,7 +60,6 @@ type GRPCExtAuthService struct {
 //
 // +kubebuilder:validation:XValidation:message="backendRef or backendRefs needs to be set",rule="has(self.backendRef) || self.backendRefs.size() > 0"
 // +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)"
-// +kubebuilder:validation:XValidation:message="Exactly one backendRef can be specified in backendRefs.",rule="has(self.backendRefs) && self.backendRefs.size()==1"
 // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service' || f.kind == 'Backend') : true"
 // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\" || f.group == 'gateway.envoyproxy.io')) : true"
 type HTTPExtAuthService struct {
diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go
index 9f19d92b4..cbdaf97ba 100644
--- a/api/v1alpha1/ext_proc_types.go
+++ b/api/v1alpha1/ext_proc_types.go
@@ -47,7 +47,6 @@ type ExtProcProcessingMode struct {
 
 // ExtProc defines the configuration for External Processing filter.
 // +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)"
-// +kubebuilder:validation:XValidation:message="Exactly one backendRef can be specified in backendRefs.",rule="has(self.backendRefs) && self.backendRefs.size()==1"
 // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service' || f.kind == 'Backend') : true"
 // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\" || f.group == 'gateway.envoyproxy.io')) : true"
 type ExtProc struct {
diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go
index ec29fb5f2..d1e6e01e2 100644
--- a/api/v1alpha1/shared_types.go
+++ b/api/v1alpha1/shared_types.go
@@ -473,12 +473,13 @@ type BackendRef struct {
 	// BackendObjectReference references a Kubernetes object that represents the backend.
 	// Only Service kind is supported for now.
 	gwapiv1.BackendObjectReference `json:",inline"`
-	// Failover This indicates whether the backend is designated as a failover.
+	// Failover indicates whether the backend is designated as a failover.
 	// Multiple failover backends can be configured.
 	// It is highly recommended to configure active or passive health checks to ensure that failover can be detected
 	// when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
 	// The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when
 	// the health of the active backends falls below 72%.
+	//
 	// +optional
 	Failover *bool `json:"failover,omitempty"`
 }
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 752317aea..b58bc5a20 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -406,6 +406,11 @@ func (in *BackendSpec) DeepCopyInto(out *BackendSpec) {
 		*out = make([]AppProtocolType, len(*in))
 		copy(*out, *in)
 	}
+	if in.Failover != nil {
+		in, out := &in.Failover, &out.Failover
+		*out = new(bool)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendSpec.
diff --git a/charts/gateway-helm/README.md b/charts/gateway-helm/README.md
index da3f7572b..4274b890b 100644
--- a/charts/gateway-helm/README.md
+++ b/charts/gateway-helm/README.md
@@ -76,6 +76,7 @@ To uninstall the chart:
 | deployment.pod.annotations."prometheus.io/port" | string | `"19001"` |  |
 | deployment.pod.annotations."prometheus.io/scrape" | string | `"true"` |  |
 | deployment.pod.labels | object | `{}` |  |
+| deployment.pod.nodeSelector | object | `{}` |  |
 | deployment.pod.tolerations | list | `[]` |  |
 | deployment.pod.topologySpreadConstraints | list | `[]` |  |
 | deployment.ports[0].name | string | `"grpc"` |  |
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
index 8c5ca5ebc..d45b3076e 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml
@@ -137,6 +137,14 @@ spec:
                 x-kubernetes-validations:
                 - message: fqdn addresses cannot be mixed with other address types
                   rule: self.all(f, has(f.fqdn)) || !self.exists(f, has(f.fqdn))
+              failover:
+                description: |-
+                  Failover indicates whether the backend is designated as a failover.
+                  It is highly recommended to configure active or passive health checks to ensure that failover can be detected
+                  when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
+                  The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when
+                  the health of the active backends falls below 72%.
+                type: boolean
             type: object
           status:
             description: Status defines the current status of Backend.
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 00fd69c57..1e095c055 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
@@ -138,7 +138,7 @@ spec:
                         properties:
                           failover:
                             description: |-
-                              Failover This indicates whether the backend is designated as a failover.
+                              Failover indicates whether the backend is designated as a failover.
                               Multiple failover backends can be configured.
                               It is highly recommended to configure active or passive health checks to ensure that failover can be detected
                               when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
@@ -859,8 +859,6 @@ spec:
                   x-kubernetes-validations:
                   - message: BackendRefs must be used, backendRef is not supported.
                     rule: '!has(self.backendRef)'
-                  - message: Exactly one backendRef can be specified in backendRefs.
-                    rule: has(self.backendRefs) && self.backendRefs.size()==1
                   - message: BackendRefs only supports Service and Backend kind.
                     rule: 'has(self.backendRefs) ? self.backendRefs.all(f, f.kind
                       == ''Service'' || f.kind == ''Backend'') : true'
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
index 7bd4b9306..46fb3818e 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -10359,7 +10359,7 @@ spec:
                                           properties:
                                             failover:
                                               description: |-
-                                                Failover This indicates whether the backend is designated as a failover.
+                                                Failover indicates whether the backend is designated as a failover.
                                                 Multiple failover backends can be configured.
                                                 It is highly recommended to configure active or passive health checks to ensure that failover can be detected
                                                 when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
@@ -11245,7 +11245,7 @@ spec:
                                           properties:
                                             failover:
                                               description: |-
-                                                Failover This indicates whether the backend is designated as a failover.
+                                                Failover indicates whether the backend is designated as a failover.
                                                 Multiple failover backends can be configured.
                                                 It is highly recommended to configure active or passive health checks to ensure that failover can be detected
                                                 when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
@@ -12209,7 +12209,7 @@ spec:
                                     properties:
                                       failover:
                                         description: |-
-                                          Failover This indicates whether the backend is designated as a failover.
+                                          Failover indicates whether the backend is designated as a failover.
                                           Multiple failover backends can be configured.
                                           It is highly recommended to configure active or passive health checks to ensure that failover can be detected
                                           when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
@@ -13108,7 +13108,7 @@ spec:
                               properties:
                                 failover:
                                   description: |-
-                                    Failover This indicates whether the backend is designated as a failover.
+                                    Failover indicates whether the backend is designated as a failover.
                                     Multiple failover backends can be configured.
                                     It is highly recommended to configure active or passive health checks to ensure that failover can be detected
                                     when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
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 d436d3873..4256957a6 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
@@ -333,7 +333,7 @@ spec:
                           properties:
                             failover:
                               description: |-
-                                Failover This indicates whether the backend is designated as a failover.
+                                Failover indicates whether the backend is designated as a failover.
                                 Multiple failover backends can be configured.
                                 It is highly recommended to configure active or passive health checks to ensure that failover can be detected
                                 when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
@@ -1018,8 +1018,6 @@ spec:
                       rule: has(self.backendRef) || self.backendRefs.size() > 0
                     - message: BackendRefs must be used, backendRef is not supported.
                       rule: '!has(self.backendRef)'
-                    - message: Exactly one backendRef can be specified in backendRefs.
-                      rule: has(self.backendRefs) && self.backendRefs.size()==1
                     - message: BackendRefs only supports Service and Backend kind.
                       rule: 'has(self.backendRefs) ? self.backendRefs.all(f, f.kind
                         == ''Service'' || f.kind == ''Backend'') : true'
@@ -1132,7 +1130,7 @@ spec:
                           properties:
                             failover:
                               description: |-
-                                Failover This indicates whether the backend is designated as a failover.
+                                Failover indicates whether the backend is designated as a failover.
                                 Multiple failover backends can be configured.
                                 It is highly recommended to configure active or passive health checks to ensure that failover can be detected
                                 when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
@@ -1833,8 +1831,6 @@ spec:
                       rule: has(self.backendRef) || self.backendRefs.size() > 0
                     - message: BackendRefs must be used, backendRef is not supported.
                       rule: '!has(self.backendRef)'
-                    - message: Exactly one backendRef can be specified in backendRefs.
-                      rule: has(self.backendRefs) && self.backendRefs.size()==1
                     - message: BackendRefs only supports Service and Backend kind.
                       rule: 'has(self.backendRefs) ? self.backendRefs.all(f, f.kind
                         == ''Service'' || f.kind == ''Backend'') : true'
diff --git a/charts/gateway-helm/templates/envoy-gateway-deployment.yaml b/charts/gateway-helm/templates/envoy-gateway-deployment.yaml
index b40c8dc54..7bf62e582 100644
--- a/charts/gateway-helm/templates/envoy-gateway-deployment.yaml
+++ b/charts/gateway-helm/templates/envoy-gateway-deployment.yaml
@@ -51,6 +51,10 @@ spec:
       affinity:
         {{- toYaml . | nindent 8 }}
       {{- end }}
+      {{- with .Values.deployment.pod.nodeSelector }}
+      nodeSelector: 
+        {{ toYaml . | nindent 8 }}
+      {{- end }}
       {{- with .Values.deployment.pod.topologySpreadConstraints }}
       topologySpreadConstraints:
         {{- toYaml . | nindent 6 }}
diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml
index 9240c4c2c..87d3aed77 100644
--- a/charts/gateway-helm/values.tmpl.yaml
+++ b/charts/gateway-helm/values.tmpl.yaml
@@ -56,6 +56,7 @@ deployment:
     labels: {}
     topologySpreadConstraints: []
     tolerations: []
+    nodeSelector: {}
 
 config:
   envoyGateway:
diff --git a/examples/extension-server/go.mod b/examples/extension-server/go.mod
index 4e61e8ed0..23a9d1345 100644
--- a/examples/extension-server/go.mod
+++ b/examples/extension-server/go.mod
@@ -4,7 +4,7 @@ go 1.22.5
 
 require (
 	github.com/envoyproxy/gateway v1.0.2
-	github.com/envoyproxy/go-control-plane v0.12.1-0.20240612043845-c54ec4ce422d
+	github.com/envoyproxy/go-control-plane v0.13.0
 	github.com/urfave/cli/v2 v2.27.2
 	google.golang.org/grpc v1.65.0
 	google.golang.org/protobuf v1.34.2
diff --git a/examples/extension-server/go.sum b/examples/extension-server/go.sum
index b9d535f8c..4ee04f537 100644
--- a/examples/extension-server/go.sum
+++ b/examples/extension-server/go.sum
@@ -11,8 +11,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/envoyproxy/go-control-plane v0.12.1-0.20240612043845-c54ec4ce422d h1:RopQsG28t61pLLZRkwzwBsi60yDsOP8RvW47A3eAcGo=
-github.com/envoyproxy/go-control-plane v0.12.1-0.20240612043845-c54ec4ce422d/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA=
+github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les=
+github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8=
 github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
 github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
 github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
diff --git a/go.mod b/go.mod
index 04178c46c..2007e84e9 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
 	github.com/docker/cli v27.1.2+incompatible
 	github.com/dominikbraun/graph v0.23.0
-	github.com/envoyproxy/go-control-plane v0.12.1-0.20240612043845-c54ec4ce422d
+	github.com/envoyproxy/go-control-plane v0.13.0
 	github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7
 	github.com/evanphx/json-patch/v5 v5.9.0
 	github.com/fatih/color v1.17.0
@@ -26,9 +26,9 @@ require (
 	github.com/google/go-containerregistry v0.20.2
 	github.com/grafana/tempo v1.5.0
 	github.com/hashicorp/go-multierror v1.1.1
-	github.com/miekg/dns v1.1.61
+	github.com/miekg/dns v1.1.62
 	github.com/ohler55/ojg v1.24.0
-	github.com/prometheus/client_golang v1.20.0
+	github.com/prometheus/client_golang v1.20.2
 	github.com/prometheus/common v0.55.0
 	github.com/spf13/cobra v1.8.1
 	github.com/spf13/pflag v1.0.5
@@ -48,7 +48,7 @@ require (
 	golang.org/x/sys v0.24.0
 	google.golang.org/protobuf v1.34.2
 	gopkg.in/yaml.v3 v3.0.1
-	helm.sh/helm/v3 v3.15.3
+	helm.sh/helm/v3 v3.15.4
 	k8s.io/api v0.31.0
 	k8s.io/apiextensions-apiserver v0.31.0
 	k8s.io/apimachinery v0.31.0
diff --git a/go.sum b/go.sum
index 8fd065bd1..105209736 100644
--- a/go.sum
+++ b/go.sum
@@ -423,8 +423,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
-github.com/envoyproxy/go-control-plane v0.12.1-0.20240612043845-c54ec4ce422d h1:RopQsG28t61pLLZRkwzwBsi60yDsOP8RvW47A3eAcGo=
-github.com/envoyproxy/go-control-plane v0.12.1-0.20240612043845-c54ec4ce422d/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA=
+github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les=
+github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
 github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
@@ -854,8 +854,8 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
 github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
 github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
 github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
-github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
-github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
+github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
+github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
 github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
 github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
 github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
@@ -973,8 +973,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
-github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
-github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
+github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
+github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -1829,8 +1829,8 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
 gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
 gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
-helm.sh/helm/v3 v3.15.3 h1:HcZDaVFe9uHa6hpsR54mJjYyRy4uz/pc6csg27nxFOc=
-helm.sh/helm/v3 v3.15.3/go.mod h1:FzSIP8jDQaa6WAVg9F+OkKz7J0ZmAga4MABtTbsb9WQ=
+helm.sh/helm/v3 v3.15.4 h1:UFHd6oZ1IN3FsUZ7XNhOQDyQ2QYknBNWRHH57e9cbHY=
+helm.sh/helm/v3 v3.15.4/go.mod h1:phOwlxqGSgppCY/ysWBNRhG3MtnpsttOzxaTK+Mt40E=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go
index b2f0ffa6e..586d422a7 100644
--- a/internal/gatewayapi/backendtrafficpolicy.go
+++ b/internal/gatewayapi/backendtrafficpolicy.go
@@ -342,11 +342,6 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 
 	ds = translateDNS(policy.Spec.ClusterSettings)
 
-	// Early return if got any errors
-	if errs != nil {
-		return errs
-	}
-
 	// Apply IR to all relevant routes
 	prefix := irRoutePrefix(route)
 
@@ -381,6 +376,14 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 			for _, r := range http.Routes {
 				// Apply if there is a match
 				if strings.HasPrefix(r.Name, prefix) {
+					if errs != nil {
+						// Return a 500 direct response
+						r.DirectResponse = &ir.DirectResponse{
+							StatusCode: 500,
+						}
+						continue
+					}
+
 					r.Traffic = &ir.TrafficFeatures{
 						RateLimit:         rl,
 						LoadBalancer:      lb,
@@ -411,7 +414,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 		}
 	}
 
-	return nil
+	return errs
 }
 
 func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.BackendTrafficPolicy, target gwapiv1a2.LocalPolicyTargetReferenceWithSectionName, gateway *GatewayContext, xdsIR XdsIRMap) error {
@@ -468,11 +471,6 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 
 	ds = translateDNS(policy.Spec.ClusterSettings)
 
-	// Early return if got any errors
-	if errs != nil {
-		return errs
-	}
-
 	// Apply IR to all the routes within the specific Gateway
 	// If the feature is already set, then skip it, since it must be have
 	// set by a policy attaching to the route
@@ -534,6 +532,14 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 				continue
 			}
 
+			if errs != nil {
+				// Return a 500 direct response
+				r.DirectResponse = &ir.DirectResponse{
+					StatusCode: 500,
+				}
+				continue
+			}
+
 			r.Traffic = &ir.TrafficFeatures{
 				RateLimit:      rl,
 				LoadBalancer:   lb,
@@ -560,7 +566,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 		}
 	}
 
-	return nil
+	return errs
 }
 
 func (t *Translator) buildRateLimit(policy *egv1a1.BackendTrafficPolicy) (*ir.RateLimit, error) {
diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go
index 9940dbabe..276a63c8b 100644
--- a/internal/gatewayapi/securitypolicy.go
+++ b/internal/gatewayapi/securitypolicy.go
@@ -805,69 +805,67 @@ func (t *Translator) buildBasicAuth(
 
 func (t *Translator) buildExtAuth(policy *egv1a1.SecurityPolicy, resources *Resources, envoyProxy *egv1a1.EnvoyProxy) (*ir.ExtAuth, error) {
 	var (
-		http       = policy.Spec.ExtAuth.HTTP
-		grpc       = policy.Spec.ExtAuth.GRPC
-		backendRef *gwapiv1.BackendObjectReference
-		protocol   ir.AppProtocol
-		ds         *ir.DestinationSetting
-		authority  string
-		err        error
-		traffic    *ir.TrafficFeatures
-		failover   *bool
+		http      = policy.Spec.ExtAuth.HTTP
+		grpc      = policy.Spec.ExtAuth.GRPC
+		backends  *egv1a1.BackendCluster
+		protocol  ir.AppProtocol
+		ds        []*ir.DestinationSetting
+		authority string
+		err       error
+		traffic   *ir.TrafficFeatures
 	)
 
-	switch {
 	// These are sanity checks, they should never happen because the API server
 	// should have caught them
-	case http != nil && grpc != nil:
+	if http == nil && grpc == nil {
+		return nil, errors.New("one of grpc or http must be specified")
+	} else if http != nil && grpc != nil {
 		return nil, errors.New("only one of grpc or http can be specified")
+	}
+
+	switch {
 	case http != nil:
-		backendRef = http.BackendRef
-		if len(http.BackendRefs) != 0 {
-			backendRef = egv1a1.ToBackendObjectReference(http.BackendRefs[0])
-			failover = http.BackendRefs[0].Failover
-		}
+		backends = &http.BackendCluster
 		protocol = ir.HTTP
-		if traffic, err = translateTrafficFeatures(http.BackendSettings); err != nil {
-			return nil, err
-		}
 	case grpc != nil:
-		backendRef = grpc.BackendRef
-		if len(grpc.BackendRefs) != 0 {
-			backendRef = egv1a1.ToBackendObjectReference(grpc.BackendRefs[0])
-			failover = grpc.BackendRefs[0].Failover
-		}
+		backends = &grpc.BackendCluster
 		protocol = ir.GRPC
-		if traffic, err = translateTrafficFeatures(grpc.BackendSettings); err != nil {
+	}
+	pnn := utils.NamespacedName(policy)
+	for _, backendRef := range backends.BackendRefs {
+		if err = t.validateExtServiceBackendReference(&backendRef.BackendObjectReference, policy.Namespace, policy.Kind, resources); err != nil {
 			return nil, err
 		}
-	// These are sanity checks, they should never happen because the API server
-	// should have caught them
-	default: // http == nil && grpc == nil:
-		return nil, errors.New("one of grpc or http must be specified")
-	}
 
-	if err = t.validateExtServiceBackendReference(backendRef, policy.Namespace, policy.Kind, resources); err != nil {
-		return nil, err
-	}
+		// Authority is the calculated hostname that will be used as the Authority header.
+		// If there are multiple backend referenced, simply use the first one - there are no good answers here.
+		// When translated to XDS, the authority is used on the filter level not on the cluster level.
+		// There's no way to translate to XDS and use a different authority for each backendref
+		if authority == "" {
+			authority = backendRefAuthority(resources, &backendRef.BackendObjectReference, policy)
+		}
 
-	authority = backendRefAuthority(resources, backendRef, policy)
-	pnn := utils.NamespacedName(policy)
-	if ds, err = t.processExtServiceDestination(
-		&egv1a1.BackendRef{BackendObjectReference: *backendRef, Failover: failover},
-		pnn,
-		KindSecurityPolicy,
-		protocol,
-		resources,
-		envoyProxy,
-	); err != nil {
-		return nil, err
+		extServiceDest, err := t.processExtServiceDestination(
+			&backendRef,
+			pnn,
+			KindSecurityPolicy,
+			protocol,
+			resources,
+			envoyProxy,
+		)
+		if err != nil {
+			return nil, err
+		}
+		ds = append(ds, extServiceDest)
 	}
 	rd := ir.RouteDestination{
-		Name:     irExtServiceDestinationName(policy, backendRef),
-		Settings: []*ir.DestinationSetting{ds},
+		Name:     irIndexedExtServiceDestinationName(pnn, egv1a1.KindSecurityPolicy, 0),
+		Settings: ds,
 	}
 
+	if traffic, err = translateTrafficFeatures(backends.BackendSettings); err != nil {
+		return nil, err
+	}
 	extAuth := &ir.ExtAuth{
 		Name:             irConfigName(policy),
 		HeadersToExtAuth: policy.Spec.ExtAuth.HeadersToExtAuth,
@@ -916,18 +914,6 @@ func backendRefAuthority(resources *Resources, backendRef *gwapiv1.BackendObject
 		*backendRef.Port)
 }
 
-func irExtServiceDestinationName(policy *egv1a1.SecurityPolicy, backendRef *gwapiv1.BackendObjectReference) string {
-	nn := types.NamespacedName{
-		Name:      string(backendRef.Name),
-		Namespace: NamespaceDerefOr(backendRef.Namespace, policy.Namespace),
-	}
-
-	return strings.ToLower(fmt.Sprintf(
-		"%s/%s",
-		irConfigName(policy),
-		nn.String()))
-}
-
 func (t *Translator) buildAuthorization(policy *egv1a1.SecurityPolicy) (*ir.Authorization, error) {
 	var (
 		authorization = policy.Spec.Authorization
diff --git a/internal/xds/extensions/extensions.gen.go b/internal/xds/extensions/extensions.gen.go
index 811bc2ab4..09713ea43 100644
--- a/internal/xds/extensions/extensions.gen.go
+++ b/internal/xds/extensions/extensions.gen.go
@@ -18,13 +18,7 @@ import (
 	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/squash/v3"
 	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/sxg/v3alpha"
 	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/client_ssl_auth/v3"
-	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/action/v3"
-	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/codecs/dubbo/v3"
-	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/codecs/http1/v3"
 	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3"
-	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3"
-	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/router/v3"
-	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/v3"
 	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/golang/v3alpha"
 	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/kafka_broker/v3"
 	_ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/kafka_mesh/v3alpha"
@@ -161,6 +155,12 @@ import (
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/dubbo_proxy/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/echo/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/ext_authz/v3"
+	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/action/v3"
+	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/codecs/dubbo/v3"
+	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/codecs/http1/v3"
+	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/matcher/v3"
+	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/router/v3"
+	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/local_ratelimit/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/mongo_proxy/v3"
@@ -223,6 +223,7 @@ import (
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/common_inputs/ssl/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/consistent_hashing/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/ip/v3"
+	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/metadata/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/runtime_fraction/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/apple/v3"
 	_ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/cares/v3"
diff --git a/site/content/en/contributions/design/envoy-extension-policy.md b/site/content/en/contributions/design/envoy-extension-policy.md
index 67af7cd6e..9ecf25988 100644
--- a/site/content/en/contributions/design/envoy-extension-policy.md
+++ b/site/content/en/contributions/design/envoy-extension-policy.md
@@ -96,12 +96,6 @@ spec:
       response:
         headers: SKIP
         body: STREAMED
-    attributes:
-      request:
-      - xds.route_metadata
-      - connection.requested_server_name
-      response:
-      - request.path
     messageTimeout: 5s
   targetRef:
     group: gateway.networking.k8s.io
diff --git a/tools/docker/envoy-gateway/Dockerfile b/tools/docker/envoy-gateway/Dockerfile
index 9d018cbf0..af75ba6ca 100644
--- a/tools/docker/envoy-gateway/Dockerfile
+++ b/tools/docker/envoy-gateway/Dockerfile
@@ -1,4 +1,4 @@
-FROM busybox as source
+FROM busybox@sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7 as source
 # Create the data directory for eg
 RUN mkdir -p /var/lib/eg
 


Test patch:
diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml
index 7f168d6ab..a8dd94a8a 100644
--- a/.github/workflows/build_and_test.yaml
+++ b/.github/workflows/build_and_test.yaml
@@ -145,7 +145,7 @@ jobs:
     - uses: ./tools/github-actions/setup-deps
 
     - name: Setup Graphviz
-      uses: ts-graphviz/setup-graphviz@v2
+      uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c  # v2.0.2
 
     # Benchmark
     - name: Run Benchmark tests
diff --git a/.github/workflows/latest_release.yaml b/.github/workflows/latest_release.yaml
index be8af0ae8..94dbd6cea 100644
--- a/.github/workflows/latest_release.yaml
+++ b/.github/workflows/latest_release.yaml
@@ -26,7 +26,7 @@ jobs:
     - uses: ./tools/github-actions/setup-deps
 
     - name: Setup Graphviz
-      uses: ts-graphviz/setup-graphviz@v2
+      uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c  # v2.0.2
 
     # Benchmark
     - name: Run Benchmark tests
@@ -46,7 +46,7 @@ jobs:
       run: cd test/benchmark && zip -r benchmark_report.zip benchmark_report
 
     - name: Upload Benchmark Report
-      uses: actions/upload-artifact@v4  # version is better be consistent with actions/download-artifact
+      uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a  # v4.3.6
       with:
         name: benchmark_report
         path: test/benchmark/benchmark_report.zip
@@ -65,7 +65,7 @@ jobs:
       run: IMAGE_PULL_POLICY=Always make generate-manifests IMAGE=envoyproxy/gateway-dev TAG=latest OUTPUT_DIR=release-artifacts
 
     - name: Download Benchmark Report
-      uses: actions/download-artifact@v4
+      uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16  # v4.1.8
       with:
         name: benchmark_report
         path: release-artifacts
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-out-of-range-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-out-of-range-error.out.yaml
index 67e8dd562..bb171e01d 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-out-of-range-error.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-out-of-range-error.out.yaml
@@ -316,6 +316,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-with-invalid-value.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-with-invalid-value.out.yaml
index cb0037b75..654c9bdab 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-with-invalid-value.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-buffer-limit-with-invalid-value.out.yaml
@@ -316,6 +316,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml
index 969005436..2b49ea237 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml
@@ -335,6 +335,8 @@ xdsIR:
               port: 8080
             protocol: GRPC
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: true
         metadata:
@@ -371,6 +373,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
@@ -391,6 +395,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer-invalid-consistent-hash-table-size.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer-invalid-consistent-hash-table-size.out.yaml
index 05e6140a2..dc2ba7fb3 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer-invalid-consistent-hash-table-size.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer-invalid-consistent-hash-table-size.out.yaml
@@ -225,6 +225,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
@@ -245,6 +247,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml
index ebce8acb4..0be116e1e 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml
@@ -178,6 +178,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml
index e5298e279..21cae9b09 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml
@@ -174,6 +174,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml
index 80e556715..0fd1f442b 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml
@@ -181,6 +181,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml
index 74ced5845..8b20cbc59 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml
@@ -160,6 +160,8 @@ xdsIR:
               port: 8080
             protocol: GRPC
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: true
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml
index 8ddcdf83c..dc80d9e73 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml
@@ -151,6 +151,8 @@ xdsIR:
               port: 8080
             protocol: GRPC
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: true
         metadata:
diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml
index 8a7e98388..bda6f990d 100644
--- a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml
@@ -158,6 +158,8 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        directResponse:
+          statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.in.yaml
index e1f50e75b..78529bf6d 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.in.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.in.yaml
@@ -101,6 +101,9 @@ securityPolicies:
           - header2
         grpc:
           backendRefs:
+            - name: service-2
+              kind: Service
+              port: 8080
             - name: backend-fqdn
               kind: Backend
               group: gateway.envoyproxy.io
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
index a89bf53a8..2957475fb 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
@@ -169,6 +169,9 @@ securityPolicies:
       failOpen: true
       grpc:
         backendRefs:
+        - kind: Service
+          name: service-2
+          port: 8080
         - group: gateway.envoyproxy.io
           kind: Backend
           name: backend-fqdn
@@ -240,10 +243,16 @@ xdsIR:
           extAuth:
             failOpen: true
             grpc:
-              authority: primary.foo.com:3000
+              authority: service-2.default:8080
               destination:
-                name: securitypolicy/default/policy-for-http-route-1/default/backend-fqdn
+                name: securitypolicy/default/policy-for-http-route-1/0
                 settings:
+                - addressType: IP
+                  endpoints:
+                  - host: 7.7.7.7
+                    port: 8080
+                  protocol: GRPC
+                  weight: 1
                 - addressType: FQDN
                   endpoints:
                   - host: primary.foo.com
@@ -278,10 +287,16 @@ xdsIR:
           extAuth:
             failOpen: true
             grpc:
-              authority: primary.foo.com:3000
+              authority: service-2.default:8080
               destination:
-                name: securitypolicy/default/policy-for-http-route-1/default/backend-fqdn
+                name: securitypolicy/default/policy-for-http-route-1/0
                 settings:
+                - addressType: IP
+                  endpoints:
+                  - host: 7.7.7.7
+                    port: 8080
+                  protocol: GRPC
+                  weight: 1
                 - addressType: FQDN
                   endpoints:
                   - host: primary.foo.com
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml
index e36258312..1c24de65e 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml
@@ -145,9 +145,9 @@ securityPolicies:
           - header1
           - header2
         grpc:
-          backendRef:
-            name: grpc-backend
-            port: 9000
+          backendRefs:
+            - name: grpc-backend
+              port: 9000
   - apiVersion: gateway.envoyproxy.io/v1alpha1
     kind: SecurityPolicy
     metadata:
@@ -161,10 +161,10 @@ securityPolicies:
       extAuth:
         failOpen: false
         http:
-          backendRef:
-            Name: http-backend
-            Namespace: envoy-gateway
-            Port: 80
+          backendRefs:
+            - Name: http-backend
+              Namespace: envoy-gateway
+              Port: 80
           Path: /auth
           headersToBackend:
             - header1
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml
index 089e50920..905b81b3c 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml
@@ -149,8 +149,8 @@ securityPolicies:
     extAuth:
       failOpen: true
       grpc:
-        backendRef:
-          name: grpc-backend
+        backendRefs:
+        - name: grpc-backend
           port: 9000
       headersToExtAuth:
       - header1
@@ -184,8 +184,8 @@ securityPolicies:
     extAuth:
       failOpen: false
       http:
-        backendRef:
-          name: http-backend
+        backendRefs:
+        - name: http-backend
           namespace: envoy-gateway
           port: 80
         headersToBackend:
@@ -263,7 +263,7 @@ xdsIR:
             grpc:
               authority: grpc-backend.default:9000
               destination:
-                name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend
+                name: securitypolicy/default/policy-for-http-route-1/0
                 settings:
                 - addressType: IP
                   endpoints:
@@ -301,7 +301,7 @@ xdsIR:
             grpc:
               authority: grpc-backend.default:9000
               destination:
-                name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend
+                name: securitypolicy/default/policy-for-http-route-1/0
                 settings:
                 - addressType: IP
                   endpoints:
@@ -339,7 +339,7 @@ xdsIR:
             http:
               authority: http-backend.envoy-gateway:80
               destination:
-                name: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend
+                name: securitypolicy/default/policy-for-gateway-1/0
                 settings:
                 - addressType: IP
                   endpoints:
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-with-backendtlspolicy.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-with-backendtlspolicy.out.yaml
index a878d1aac..ac1b52a58 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-with-backendtlspolicy.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-with-backendtlspolicy.out.yaml
@@ -322,7 +322,7 @@ xdsIR:
             grpc:
               authority: grpc-backend.default:9000
               destination:
-                name: securitypolicy/default/policy-for-http-route/default/grpc-backend
+                name: securitypolicy/default/policy-for-http-route/0
                 settings:
                 - addressType: IP
                   endpoints:
@@ -365,7 +365,7 @@ xdsIR:
             http:
               authority: http-backend.envoy-gateway:80
               destination:
-                name: securitypolicy/default/policy-for-gateway/envoy-gateway/http-backend
+                name: securitypolicy/default/policy-for-gateway/0
                 settings:
                 - addressType: IP
                   endpoints:
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml
index f8395d241..905b81b3c 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml
@@ -263,7 +263,7 @@ xdsIR:
             grpc:
               authority: grpc-backend.default:9000
               destination:
-                name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend
+                name: securitypolicy/default/policy-for-http-route-1/0
                 settings:
                 - addressType: IP
                   endpoints:
@@ -301,7 +301,7 @@ xdsIR:
             grpc:
               authority: grpc-backend.default:9000
               destination:
-                name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend
+                name: securitypolicy/default/policy-for-http-route-1/0
                 settings:
                 - addressType: IP
                   endpoints:
@@ -339,7 +339,7 @@ xdsIR:
             http:
               authority: http-backend.envoy-gateway:80
               destination:
-                name: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend
+                name: securitypolicy/default/policy-for-gateway-1/0
                 settings:
                 - addressType: IP
                   endpoints:
diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-auth.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-auth.yaml
index bedbbae99..0453e1341 100644
--- a/internal/xds/translator/testdata/in/xds-ir/ext-auth.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/ext-auth.yaml
@@ -37,6 +37,12 @@ http:
               destination:
                 name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend
                 settings:
+                  - addressType: IP
+                    endpoints:
+                      - host: 8.8.4.4
+                        port: 9001
+                    protocol: GRPC
+                    weight: 1
                   - addressType: IP
                     endpoints:
                       - host: 8.8.8.8
diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.endpoints.yaml
index 2c0f91a63..701d34b96 100644
--- a/internal/xds/translator/testdata/out/xds-ir/ext-auth.endpoints.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.endpoints.yaml
@@ -36,6 +36,16 @@
       region: httproute/default/httproute-2/rule/0/backend/0
 - clusterName: securitypolicy/default/policy-for-http-route-1/default/grpc-backend
   endpoints:
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 8.8.4.4
+            portValue: 9001
+      loadBalancingWeight: 1
+    loadBalancingWeight: 1
+    locality:
+      region: securitypolicy/default/policy-for-http-route-1/default/grpc-backend/backend/0
   - lbEndpoints:
     - endpoint:
         address:
@@ -45,7 +55,7 @@
       loadBalancingWeight: 1
     loadBalancingWeight: 1
     locality:
-      region: securitypolicy/default/policy-for-http-route-1/default/grpc-backend/backend/0
+      region: securitypolicy/default/policy-for-http-route-1/default/grpc-backend/backend/1
 - clusterName: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend
   endpoints:
   - lbEndpoints:
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 7807853c8..39a7e955c 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -364,7 +364,7 @@ _Appears in:_
 | `name` | _[ObjectName](#objectname)_ |  true  | Name is the name of the referent. |
 | `namespace` | _[Namespace](#namespace)_ |  false  | Namespace is the namespace of the backend. When unspecified, the local<br />namespace is inferred.<br /><br />Note that when a namespace different than the local namespace is specified,<br />a ReferenceGrant object is required in the referent namespace to allow that<br />namespace's owner to accept the reference. See the ReferenceGrant<br />documentation for details.<br /><br />Support: Core |
 | `port` | _[PortNumber](#portnumber)_ |  false  | Port specifies the destination port number to use for this resource.<br />Port is required when the referent is a Kubernetes Service. In this<br />case, the port number is the service port number, not the target port.<br />For other resources, destination port might be derived from the referent<br />resource or this field. |
-| `failover` | _boolean_ |  false  | Failover This indicates whether the backend is designated as a failover.<br />Multiple failover backends can be configured.<br />It is highly recommended to configure active or passive health checks to ensure that failover can be detected<br />when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.<br />The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when<br />the health of the active backends falls below 72%. |
+| `failover` | _boolean_ |  false  | Failover indicates whether the backend is designated as a failover.<br />Multiple failover backends can be configured.<br />It is highly recommended to configure active or passive health checks to ensure that failover can be detected<br />when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.<br />The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when<br />the health of the active backends falls below 72%. |
 
 
 #### BackendSpec
diff --git a/site/content/en/latest/install/gateway-helm-api.md b/site/content/en/latest/install/gateway-helm-api.md
index 9f2046a53..04167b4eb 100644
--- a/site/content/en/latest/install/gateway-helm-api.md
+++ b/site/content/en/latest/install/gateway-helm-api.md
@@ -40,6 +40,7 @@ The Helm chart for Envoy Gateway
 | deployment.pod.annotations."prometheus.io/port" | string | `"19001"` |  |
 | deployment.pod.annotations."prometheus.io/scrape" | string | `"true"` |  |
 | deployment.pod.labels | object | `{}` |  |
+| deployment.pod.nodeSelector | object | `{}` |  |
 | deployment.pod.tolerations | list | `[]` |  |
 | deployment.pod.topologySpreadConstraints | list | `[]` |  |
 | deployment.ports[0].name | string | `"grpc"` |  |
diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md
index 7807853c8..39a7e955c 100644
--- a/site/content/zh/latest/api/extension_types.md
+++ b/site/content/zh/latest/api/extension_types.md
@@ -364,7 +364,7 @@ _Appears in:_
 | `name` | _[ObjectName](#objectname)_ |  true  | Name is the name of the referent. |
 | `namespace` | _[Namespace](#namespace)_ |  false  | Namespace is the namespace of the backend. When unspecified, the local<br />namespace is inferred.<br /><br />Note that when a namespace different than the local namespace is specified,<br />a ReferenceGrant object is required in the referent namespace to allow that<br />namespace's owner to accept the reference. See the ReferenceGrant<br />documentation for details.<br /><br />Support: Core |
 | `port` | _[PortNumber](#portnumber)_ |  false  | Port specifies the destination port number to use for this resource.<br />Port is required when the referent is a Kubernetes Service. In this<br />case, the port number is the service port number, not the target port.<br />For other resources, destination port might be derived from the referent<br />resource or this field. |
-| `failover` | _boolean_ |  false  | Failover This indicates whether the backend is designated as a failover.<br />Multiple failover backends can be configured.<br />It is highly recommended to configure active or passive health checks to ensure that failover can be detected<br />when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.<br />The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when<br />the health of the active backends falls below 72%. |
+| `failover` | _boolean_ |  false  | Failover indicates whether the backend is designated as a failover.<br />Multiple failover backends can be configured.<br />It is highly recommended to configure active or passive health checks to ensure that failover can be detected<br />when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.<br />The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when<br />the health of the active backends falls below 72%. |
 
 
 #### BackendSpec
diff --git a/site/content/zh/latest/install/gateway-helm-api.md b/site/content/zh/latest/install/gateway-helm-api.md
index 9f2046a53..04167b4eb 100644
--- a/site/content/zh/latest/install/gateway-helm-api.md
+++ b/site/content/zh/latest/install/gateway-helm-api.md
@@ -40,6 +40,7 @@ The Helm chart for Envoy Gateway
 | deployment.pod.annotations."prometheus.io/port" | string | `"19001"` |  |
 | deployment.pod.annotations."prometheus.io/scrape" | string | `"true"` |  |
 | deployment.pod.labels | object | `{}` |  |
+| deployment.pod.nodeSelector | object | `{}` |  |
 | deployment.pod.tolerations | list | `[]` |  |
 | deployment.pod.topologySpreadConstraints | list | `[]` |  |
 | deployment.ports[0].name | string | `"grpc"` |  |
diff --git a/test/cel-validation/securitypolicy_test.go b/test/cel-validation/securitypolicy_test.go
index 2ca001cd0..cbc0145aa 100644
--- a/test/cel-validation/securitypolicy_test.go
+++ b/test/cel-validation/securitypolicy_test.go
@@ -685,7 +685,6 @@ func TestSecurityPolicyTarget(t *testing.T) {
 			},
 			wantErrors: []string{
 				"BackendRefs must be used, backendRef is not supported.",
-				"Exactly one backendRef can be specified in backendRefs.",
 			},
 		},
 		{
@@ -782,7 +781,6 @@ func TestSecurityPolicyTarget(t *testing.T) {
 			},
 			wantErrors: []string{
 				"BackendRefs must be used, backendRef is not supported.",
-				"Exactly one backendRef can be specified in backendRefs.",
 			},
 		},
 		{
diff --git a/test/e2e/testdata/backendtrafficpolicy-translation-failed.yaml b/test/e2e/testdata/backendtrafficpolicy-translation-failed.yaml
new file mode 100644
index 000000000..a5a6a7af3
--- /dev/null
+++ b/test/e2e/testdata/backendtrafficpolicy-translation-failed.yaml
@@ -0,0 +1,42 @@
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: http-ratelimit
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: same-namespace
+  hostnames: ["www.example.com"]
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /myapp  # This is the path that will be protected by OIDC
+      backendRefs:
+        - name: infra-backend-v1
+          port: 8080
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: policy-httproute
+  namespace: gateway-conformance-infra
+spec:
+  targetRefs:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: http-ratelimit
+  rateLimit:
+    type: Global
+    global:
+      rules:
+        - clientSelectors:
+            - headers:
+                - name: x-user-id
+                  type: RegularExpression
+                  value: "*.illegal.regex"
+          limit:
+            requests: 10
+            unit: Hour
+      type: Global
diff --git a/test/e2e/tests/backendtrafficpolicy_translation_failed.go b/test/e2e/tests/backendtrafficpolicy_translation_failed.go
new file mode 100644
index 000000000..9701596de
--- /dev/null
+++ b/test/e2e/tests/backendtrafficpolicy_translation_failed.go
@@ -0,0 +1,62 @@
+// 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 (
+	"testing"
+
+	"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"
+)
+
+func init() {
+	ConformanceTests = append(ConformanceTests, FailedBackendTrafficPolicyDirectResponseTest)
+}
+
+// FailedBackendTrafficPolicyDirectResponseTest tests the direct 500 response for HTTPRoute targeted by a failed BackendTrafficPolicy.
+var FailedBackendTrafficPolicyDirectResponseTest = suite.ConformanceTest{
+	ShortName:   "FailedBackendTrafficPolicyDirectResponse",
+	Description: "Test direct 500 response when failed to translate BackendTrafficPolicy",
+	Manifests:   []string{"testdata/backendtrafficpolicy-translation-failed.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		t.Run("http route with failed BackendTrafficPolicy", func(t *testing.T) {
+			ns := "gateway-conformance-infra"
+			routeNN := types.NamespacedName{Name: "http-ratelimit", Namespace: ns}
+			gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
+			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+			ancestorRef := gwapiv1a2.ParentReference{
+				Group:     gatewayapi.GroupPtr(gwapiv1.GroupName),
+				Kind:      gatewayapi.KindPtr(gatewayapi.KindGateway),
+				Namespace: gatewayapi.NamespacePtr(gwNN.Namespace),
+				Name:      gwapiv1.ObjectName(gwNN.Name),
+			}
+			BackendTrafficPolicyMustFail(t, suite.Client, types.NamespacedName{Name: "policy-httproute", Namespace: ns}, suite.ControllerName, ancestorRef, "")
+
+			expectedResponse := http.ExpectedResponse{
+				Request: http.Request{
+					Host: "www.example.com",
+					Path: "/myapp",
+				},
+				Response: http.Response{
+					StatusCode: 500,
+				},
+				Namespace: ns,
+			}
+
+			http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+		})
+	},
+}
diff --git a/test/e2e/tests/utils.go b/test/e2e/tests/utils.go
index c08b17685..c7b3fa381 100644
--- a/test/e2e/tests/utils.go
+++ b/test/e2e/tests/utils.go
@@ -161,6 +161,33 @@ func BackendTrafficPolicyMustBeAccepted(t *testing.T, client client.Client, poli
 	require.NoErrorf(t, waitErr, "error waiting for BackendTrafficPolicy to be accepted")
 }
 
+// BackendTrafficPolicyMustFail waits for an BackendTrafficPolicy to fail with the specified reason.
+func BackendTrafficPolicyMustFail(
+	t *testing.T, client client.Client, policyName types.NamespacedName,
+	controllerName string, ancestorRef gwapiv1a2.ParentReference, message string,
+) {
+	t.Helper()
+
+	policy := &egv1a1.BackendTrafficPolicy{}
+	waitErr := wait.PollUntilContextTimeout(
+		context.Background(), 1*time.Second, 60*time.Second,
+		true, func(ctx context.Context) (bool, error) {
+			err := client.Get(ctx, policyName, policy)
+			if err != nil {
+				return false, fmt.Errorf("error fetching BackendTrafficPolicy: %w", err)
+			}
+
+			if policyFailAcceptedByAncestor(policy.Status.Ancestors, controllerName, ancestorRef, message) {
+				t.Logf("BackendTrafficPolicy has been failed: %v", policy)
+				return true, nil
+			}
+
+			return false, nil
+		})
+
+	require.NoErrorf(t, waitErr, "error waiting for BackendTrafficPolicy to fail with message: %s policy %v", message, policy)
+}
+
 // ClientTrafficPolicyMustBeAccepted waits for the specified ClientTrafficPolicy to be accepted.
 func ClientTrafficPolicyMustBeAccepted(t *testing.T, client client.Client, policyName types.NamespacedName, controllerName string, ancestorRef gwapiv1a2.ParentReference) {
 	t.Helper()