Repository: envoyproxy/gateway

Issue:
Options to configure client-side rate limiter
*Description*:

Running 3 envoy-gateway controllers with leader election, I'm often seeing the gateway's rate limit themselves ("client rate limiter"). There does not seem to be a way to configure the client side qps and burst like might be found in other controllers.

```
envoy-gateway 2025-04-25T01:15:12.148Z    ERROR    provider    leaderelection/leaderelection.go:429    Failed to update lock optimistically: client rate limiter Wait returned an error: context deadline exceeded, falling back to slow path    {"runner": "provider"}                                                     │
│ envoy-gateway 2025-04-25T01:15:12.149Z    ERROR    provider    leaderelection/leaderelection.go:436    error retrieving resource lock ingress/5b9825d2.gateway.envoyproxy.io: client rate limiter Wait returned an error: context deadline exceeded    {"runner": "provider"}                                               │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    leaderelection/leaderelection.go:297    failed to renew lease ingress/5b9825d2.gateway.envoyproxy.io: context deadline exceeded    {"runner": "provider"}
envoy-gateway 2025-04-25T01:15:12.149Z    ERROR    provider    runner/runner.go:65    unable to start provider    {"runner": "provider", "error": "leader election lost"}                                                                                                                                                   │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    manager/internal.go:538    Stopping and waiting for non leader election runnables    {"runner": "provider"}                                                                                                                                                   │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    manager/internal.go:542    Stopping and waiting for leader election runnables    {"runner": "provider"}                                                                                                                                                       │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    controller/controller.go:262    Shutdown signal received, waiting for all workers to finish    {"runner": "provider", "controller": "gatewayapi-1745543133"}                                                                                                  │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    controller/controller.go:264    All workers finished    {"runner": "provider", "controller": "gatewayapi-1745543133"}                                                                                                                                         │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    manager/internal.go:550    Stopping and waiting for caches    {"runner": "provider"}                                                                                                                                                                          │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    kubernetes/status_updater.go:143    stopped status update handler    {"runner": "provider"}                                                                                                                                                                   │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    manager/internal.go:554    Stopping and waiting for webhooks    {"runner": "provider"}                                                                                                                                                                        │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    manager/internal.go:557    Stopping and waiting for HTTP servers    {"runner": "provider"}                                                                                                                                                                    │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    manager/internal.go:561    Wait completed, proceeding to shutdown the manager    {"runner": "provider"}                                                                                                                                                       │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider    manager/server.go:68    shutting down server    {"runner": "provider", "name": "health probe", "addr": ":8081"}                                                                                                                                               │
│ envoy-gateway 2025-04-25T01:15:12.149Z    INFO    provider.controller-runtime.metrics    server/server.go:254    Shutting down metrics server with timeout of 1 minute    {"runner": "provider"}                                                                                                                            │
│ envoy-gateway 2025-04-25T01:15:52.936Z    INFO    cmd/server.go:83    shutting down
```

Another option might be to extend the leader election leases so they don't have to hit the apiserver so often I suspect. 

```
leaderElection:
  leaseDuration: 15s
  renewDeadline: 10s
  retryPeriod: 2s
```

With the defaults, leader election seems to rate limit itself often enough to cause gateway pod restarts and churn.  Is running with multiple replicas, but no election valid? It's unfortunate that the main cause of gateways going down is their own leader election mechanism it seems.


>Describe the desired behavior, what scenario it enables and how it would be used.

First, is it intended to have such short-lived leases? Which effectively require constant action. And if so, are the client rate limits tuned for it? Should we be able to tune it or are we holding it wrong?

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

Envoy Gateway v1.3.2


Discussion:
@arkodg: cc @alexwo @alexwo: /assign@dghubble: Extending the leases does seem to help (to force the clients to request less often) reduce frequency of leader changes, but with the tradeoff of less resiliency in outages I guess.

```
                leaseDuration = "90s"
                renewDeadline = "60s"
                retryPeriod   = "5s"
```

Solution patch:
diff --git a/api/v1alpha1/envoygateway_helpers.go b/api/v1alpha1/envoygateway_helpers.go
index daa84ce41..0054a8a37 100644
--- a/api/v1alpha1/envoygateway_helpers.go
+++ b/api/v1alpha1/envoygateway_helpers.go
@@ -50,6 +50,11 @@ func (e *EnvoyGateway) SetEnvoyGatewayDefaults() {
 	if e.Provider.Kubernetes.LeaderElection == nil {
 		e.Provider.Kubernetes.LeaderElection = DefaultLeaderElection()
 	}
+
+	if e.Provider.Kubernetes.Client == nil {
+		e.Provider.Kubernetes.Client = DefaultKubernetesClient()
+	}
+
 	if e.Gateway == nil {
 		e.Gateway = DefaultGateway()
 	}
@@ -106,6 +111,16 @@ func DefaultLeaderElection() *LeaderElection {
 	}
 }
 
+// DefaultKubernetesClient returns a new DefaultKubernetesClient with default parameters.
+func DefaultKubernetesClient() *KubernetesClient {
+	return &KubernetesClient{
+		RateLimit: &KubernetesClientRateLimit{
+			QPS:   ptr.To(DefaultKubernetesClientQPS),
+			Burst: ptr.To(DefaultKubernetesClientBurst),
+		},
+	}
+}
+
 // DefaultGateway returns a new Gateway with default configuration parameters.
 func DefaultGateway() *Gateway {
 	return &Gateway{
@@ -171,6 +186,7 @@ func DefaultEnvoyGatewayProvider() *EnvoyGatewayProvider {
 		Type: ProviderTypeKubernetes,
 		Kubernetes: &EnvoyGatewayKubernetesProvider{
 			LeaderElection: DefaultLeaderElection(),
+			Client:         DefaultKubernetesClient(),
 		},
 	}
 }
@@ -222,6 +238,9 @@ func (r *EnvoyGatewayProvider) GetEnvoyGatewayKubeProvider() *EnvoyGatewayKubern
 		if r.Kubernetes.LeaderElection == nil {
 			r.Kubernetes.LeaderElection = DefaultLeaderElection()
 		}
+		if r.Kubernetes.Client == nil {
+			r.Kubernetes.Client = DefaultKubernetesClient()
+		}
 		return r.Kubernetes
 	}
 
@@ -229,6 +248,10 @@ func (r *EnvoyGatewayProvider) GetEnvoyGatewayKubeProvider() *EnvoyGatewayKubern
 		r.Kubernetes.LeaderElection = DefaultLeaderElection()
 	}
 
+	if r.Kubernetes.Client == nil {
+		r.Kubernetes.Client = DefaultKubernetesClient()
+	}
+
 	if r.Kubernetes.RateLimitDeployment == nil {
 		r.Kubernetes.RateLimitDeployment = DefaultKubernetesDeployment(DefaultRateLimitImage)
 	}
@@ -276,3 +299,12 @@ func (logging *EnvoyGatewayLogging) SetEnvoyGatewayLoggingDefaults() {
 		logging.Level[LogComponentGatewayDefault] = LogLevelInfo
 	}
 }
+
+func (kcr *KubernetesClientRateLimit) GetQPSAndBurst() (float32, int) {
+	if kcr == nil {
+		return float32(DefaultKubernetesClientQPS), int(DefaultKubernetesClientBurst)
+	}
+	qps := ptr.Deref(kcr.QPS, DefaultKubernetesClientQPS)
+	burst := ptr.Deref(kcr.Burst, DefaultKubernetesClientBurst)
+	return float32(qps), int(burst)
+}
diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go
index 1af2dd458..4d83f18e4 100644
--- a/api/v1alpha1/envoygateway_types.go
+++ b/api/v1alpha1/envoygateway_types.go
@@ -24,6 +24,10 @@ const (
 	GatewayMetricsPort = 19001
 	// GatewayMetricsHost is the host of envoy gateway metrics server.
 	GatewayMetricsHost = "0.0.0.0"
+	// DefaultKubernetesClientQPS defines the default QPS limit for the Kubernetes client.
+	DefaultKubernetesClientQPS int32 = 50
+	// DefaultKubernetesClientBurst defines the default Burst limit for the Kubernetes client.
+	DefaultKubernetesClientBurst int32 = 100
 )
 
 // +kubebuilder:object:root=true
@@ -91,6 +95,26 @@ type EnvoyGatewaySpec struct {
 	ExtensionAPIs *ExtensionAPISettings `json:"extensionApis,omitempty"`
 }
 
+type KubernetesClient struct {
+	// RateLimit defines the rate limit settings for the Kubernetes client.
+	RateLimit *KubernetesClientRateLimit `json:"rateLimit,omitempty"`
+}
+
+// KubernetesClientRateLimit defines the rate limit settings for the Kubernetes client.
+type KubernetesClientRateLimit struct {
+	// QPS defines the queries per second limit for the Kubernetes client.
+	// +optional
+	// +kubebuilder:validation:Minimum=1
+	// +kubebuilder:default=50
+	QPS *int32 `json:"qps,omitempty"`
+
+	// Burst defines the maximum burst of requests allowed when tokens have accumulated.
+	// +optional
+	// +kubebuilder:validation:Minimum=1
+	// +kubebuilder:default=100
+	Burst *int32 `json:"burst,omitempty"`
+}
+
 // LeaderElection defines the desired leader election settings.
 type LeaderElection struct {
 	// LeaseDuration defines the time non-leader contenders will wait before attempting to claim leadership.
@@ -225,7 +249,8 @@ type EnvoyGatewayKubernetesProvider struct {
 	// ShutdownManager defines the configuration for the shutdown manager.
 	// +optional
 	ShutdownManager *ShutdownManager `json:"shutdownManager,omitempty"`
-
+	// Client holds the configuration for the Kubernetes client.
+	Client *KubernetesClient `json:"client,omitempty"`
 	// TopologyInjector defines the configuration for topology injector MutatatingWebhookConfiguration
 	// +optional
 	TopologyInjector *EnvoyGatewayTopologyInjector `json:"proxyTopologyInjector,omitempty"`
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index f8762564a..ed3f92b80 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -1753,6 +1753,11 @@ func (in *EnvoyGatewayKubernetesProvider) DeepCopyInto(out *EnvoyGatewayKubernet
 		*out = new(ShutdownManager)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.Client != nil {
+		in, out := &in.Client, &out.Client
+		*out = new(KubernetesClient)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.TopologyInjector != nil {
 		in, out := &in.TopologyInjector, &out.TopologyInjector
 		*out = new(EnvoyGatewayTopologyInjector)
@@ -3752,6 +3757,51 @@ func (in *JWTProvider) DeepCopy() *JWTProvider {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KubernetesClient) DeepCopyInto(out *KubernetesClient) {
+	*out = *in
+	if in.RateLimit != nil {
+		in, out := &in.RateLimit, &out.RateLimit
+		*out = new(KubernetesClientRateLimit)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesClient.
+func (in *KubernetesClient) DeepCopy() *KubernetesClient {
+	if in == nil {
+		return nil
+	}
+	out := new(KubernetesClient)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KubernetesClientRateLimit) DeepCopyInto(out *KubernetesClientRateLimit) {
+	*out = *in
+	if in.QPS != nil {
+		in, out := &in.QPS, &out.QPS
+		*out = new(int32)
+		**out = **in
+	}
+	if in.Burst != nil {
+		in, out := &in.Burst, &out.Burst
+		*out = new(int32)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesClientRateLimit.
+func (in *KubernetesClientRateLimit) DeepCopy() *KubernetesClientRateLimit {
+	if in == nil {
+		return nil
+	}
+	out := new(KubernetesClientRateLimit)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KubernetesContainerSpec) DeepCopyInto(out *KubernetesContainerSpec) {
 	*out = *in
diff --git a/internal/infrastructure/manager.go b/internal/infrastructure/manager.go
index 3e1a0d811..b70b7505e 100644
--- a/internal/infrastructure/manager.go
+++ b/internal/infrastructure/manager.go
@@ -56,7 +56,9 @@ func NewManager(ctx context.Context, cfg *config.Server, logger logging.Logger)
 }
 
 func newManagerForKubernetes(cfg *config.Server) (Manager, error) {
-	cli, err := client.New(clicfg.GetConfigOrDie(), client.Options{Scheme: envoygateway.GetScheme()})
+	clientConfig := clicfg.GetConfigOrDie()
+	clientConfig.QPS, clientConfig.Burst = cfg.EnvoyGateway.Provider.Kubernetes.Client.RateLimit.GetQPSAndBurst()
+	cli, err := client.New(clientConfig, client.Options{Scheme: envoygateway.GetScheme()})
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/provider/kubernetes/kubernetes.go b/internal/provider/kubernetes/kubernetes.go
index 65f2c1e3e..078dc8fd3 100644
--- a/internal/provider/kubernetes/kubernetes.go
+++ b/internal/provider/kubernetes/kubernetes.go
@@ -37,6 +37,11 @@ type Provider struct {
 	manager manager.Manager
 }
 
+const (
+	QPS   = 50
+	BURST = 100
+)
+
 // Exposed to allow disabling health probe listener in tests.
 var (
 	healthProbeBindAddress = ":8081"
@@ -69,6 +74,8 @@ func New(ctx context.Context, restCfg *rest.Config, svrCfg *ec.Server, resources
 	log.SetLogger(mgrOpts.Logger)
 	klog.SetLogger(mgrOpts.Logger)
 
+	restCfg.QPS, restCfg.Burst = svrCfg.EnvoyGateway.Provider.Kubernetes.Client.RateLimit.GetQPSAndBurst()
+
 	if !ptr.Deref(svrCfg.EnvoyGateway.Provider.Kubernetes.LeaderElection.Disable, false) {
 		mgrOpts.LeaderElection = true
 		if svrCfg.EnvoyGateway.Provider.Kubernetes.LeaderElection.LeaseDuration != nil {



Test patch:
diff --git a/internal/envoygateway/config/decoder_test.go b/internal/envoygateway/config/decoder_test.go
index 5bbbb959e..cd49d89ff 100644
--- a/internal/envoygateway/config/decoder_test.go
+++ b/internal/envoygateway/config/decoder_test.go
@@ -344,6 +344,30 @@ func TestDecode(t *testing.T) {
 			},
 			expect: true,
 		},
+		{
+			in: inPath + "gateway-k8s-client-ratelimit.yaml",
+			out: &egv1a1.EnvoyGateway{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       egv1a1.KindEnvoyGateway,
+					APIVersion: egv1a1.GroupVersion.String(),
+				},
+				EnvoyGatewaySpec: egv1a1.EnvoyGatewaySpec{
+					Gateway: egv1a1.DefaultGateway(),
+					Provider: &egv1a1.EnvoyGatewayProvider{
+						Type: egv1a1.ProviderTypeKubernetes,
+						Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{
+							Client: &egv1a1.KubernetesClient{
+								RateLimit: &egv1a1.KubernetesClientRateLimit{
+									QPS:   ptr.To[int32](500),
+									Burst: ptr.To[int32](1000),
+								},
+							},
+						},
+					},
+				},
+			},
+			expect: true,
+		},
 	}
 
 	for _, tc := range testCases {
diff --git a/internal/envoygateway/config/testdata/decoder/in/gateway-global-ratelimit.yaml b/internal/envoygateway/config/testdata/decoder/in/gateway-global-ratelimit.yaml
index 496ff0a21..ede23df7f 100644
--- a/internal/envoygateway/config/testdata/decoder/in/gateway-global-ratelimit.yaml
+++ b/internal/envoygateway/config/testdata/decoder/in/gateway-global-ratelimit.yaml
@@ -5,6 +5,10 @@ gateway:
 provider:
   type: Kubernetes
   kubernetes:
+    client:
+      rateLimit:
+        qps: 50
+        burst: 100
     leaderElection:
       leaseDuration: 15s
       renewDeadline: 10s
diff --git a/internal/envoygateway/config/testdata/decoder/in/gateway-k8s-client-ratelimit.yaml b/internal/envoygateway/config/testdata/decoder/in/gateway-k8s-client-ratelimit.yaml
new file mode 100644
index 000000000..4f5b5584f
--- /dev/null
+++ b/internal/envoygateway/config/testdata/decoder/in/gateway-k8s-client-ratelimit.yaml
@@ -0,0 +1,11 @@
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyGateway
+gateway:
+  controllerName: gateway.envoyproxy.io/gatewayclass-controller
+provider:
+  type: Kubernetes
+  kubernetes:
+    client:
+      rateLimit:
+        qps: 500
+        burst: 1000
diff --git a/internal/envoygateway/config/testdata/decoder/in/kube-provider.yaml b/internal/envoygateway/config/testdata/decoder/in/kube-provider.yaml
index f59abe950..02bff5da5 100644
--- a/internal/envoygateway/config/testdata/decoder/in/kube-provider.yaml
+++ b/internal/envoygateway/config/testdata/decoder/in/kube-provider.yaml
@@ -3,6 +3,10 @@ kind: EnvoyGateway
 provider:
   type: Kubernetes
   kubernetes:
+    client:
+      rateLimit:
+        qps: 50
+        burst: 100
     leaderElection:
       leaseDuration: 15s
       renewDeadline: 10s
diff --git a/internal/envoygateway/config/testdata/decoder/in/provider-mixing-gateway.yaml b/internal/envoygateway/config/testdata/decoder/in/provider-mixing-gateway.yaml
index 339ed976c..01ef6352b 100644
--- a/internal/envoygateway/config/testdata/decoder/in/provider-mixing-gateway.yaml
+++ b/internal/envoygateway/config/testdata/decoder/in/provider-mixing-gateway.yaml
@@ -3,6 +3,10 @@ kind: EnvoyGateway
 provider:
   type: Kubernetes
   kubernetes:
+    client:
+      rateLimit:
+        qps: 50
+        burst: 100
     leaderElection:
       leaseDuration: 15s
       renewDeadline: 10s
diff --git a/internal/envoygateway/config/testdata/decoder/in/provider-with-gateway.yaml b/internal/envoygateway/config/testdata/decoder/in/provider-with-gateway.yaml
index 12492974c..8cdf53735 100644
--- a/internal/envoygateway/config/testdata/decoder/in/provider-with-gateway.yaml
+++ b/internal/envoygateway/config/testdata/decoder/in/provider-with-gateway.yaml
@@ -3,6 +3,10 @@ kind: EnvoyGateway
 provider:
   type: Kubernetes
   kubernetes:
+    client:
+      rateLimit:
+        qps: 50
+        burst: 100
     leaderElection:
       leaseDuration: 15s
       renewDeadline: 10s
diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go
index 15be47eaa..81d91536b 100644
--- a/internal/provider/kubernetes/kubernetes_test.go
+++ b/internal/provider/kubernetes/kubernetes_test.go
@@ -1276,6 +1276,7 @@ func TestNamespacedProvider(t *testing.T) {
 			Namespaces: []string{"ns1", "ns2"},
 		},
 		LeaderElection: egv1a1.DefaultLeaderElection(),
+		Client:         egv1a1.DefaultKubernetesClient(),
 	}
 
 	// Disable webhook server for provider test to avoid non-existent cert errors
@@ -1340,6 +1341,7 @@ func TestNamespaceSelectorProvider(t *testing.T) {
 			NamespaceSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"label-1": "true", "label-2": "true"}},
 		},
 		LeaderElection: egv1a1.DefaultLeaderElection(),
+		Client:         egv1a1.DefaultKubernetesClient(),
 	}
 
 	// Disable webhook server for provider test to avoid non-existent cert errors
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 47b0c179c..2c7a47664 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -1268,6 +1268,7 @@ _Appears in:_
 | `watch` | _[KubernetesWatchMode](#kuberneteswatchmode)_ |  false  |  | Watch holds configuration of which input resources should be watched and reconciled. |
 | `leaderElection` | _[LeaderElection](#leaderelection)_ |  false  |  | LeaderElection specifies the configuration for leader election.<br />If it's not set up, leader election will be active by default, using Kubernetes' standard settings. |
 | `shutdownManager` | _[ShutdownManager](#shutdownmanager)_ |  false  |  | ShutdownManager defines the configuration for the shutdown manager. |
+| `client` | _[KubernetesClient](#kubernetesclient)_ |  true  |  | Client holds the configuration for the Kubernetes client. |
 | `proxyTopologyInjector` | _[EnvoyGatewayTopologyInjector](#envoygatewaytopologyinjector)_ |  false  |  | TopologyInjector defines the configuration for topology injector MutatatingWebhookConfiguration |
 
 
@@ -2683,6 +2684,35 @@ _Appears in:_
 
 
 
+#### KubernetesClient
+
+
+
+
+
+_Appears in:_
+- [EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider)
+
+| Field | Type | Required | Default | Description |
+| ---   | ---  | ---      | ---     | ---         |
+| `rateLimit` | _[KubernetesClientRateLimit](#kubernetesclientratelimit)_ |  true  |  | RateLimit defines the rate limit settings for the Kubernetes client. |
+
+
+#### KubernetesClientRateLimit
+
+
+
+KubernetesClientRateLimit defines the rate limit settings for the Kubernetes client.
+
+_Appears in:_
+- [KubernetesClient](#kubernetesclient)
+
+| Field | Type | Required | Default | Description |
+| ---   | ---  | ---      | ---     | ---         |
+| `qps` | _integer_ |  false  | 50 | QPS defines the queries per second limit for the Kubernetes client. |
+| `burst` | _integer_ |  false  | 100 | Burst defines the maximum burst of requests allowed when tokens have accumulated. |
+
+
 #### KubernetesContainerSpec
 
 
diff --git a/test/fuzz/oss_fuzz_build.sh b/test/fuzz/oss_fuzz_build.sh
index 616bd45f3..a85878350 100755
--- a/test/fuzz/oss_fuzz_build.sh
+++ b/test/fuzz/oss_fuzz_build.sh
@@ -35,5 +35,3 @@ go mod tidy
 # compile native-format fuzzers
 compile_native_go_fuzzer github.com/envoyproxy/gateway/test/fuzz FuzzGatewayAPIToXDS FuzzGatewayAPIToXDS
 compile_native_go_fuzzer github.com/envoyproxy/gateway/test/fuzz FuzzGatewayClassToXDS FuzzGatewayClassToXDS
-compile_native_go_fuzzer github.com/envoyproxy/gateway/test/fuzz FuzzReverseStringBugSimulator FuzzReverseStringBugSimulator
-
diff --git a/test/fuzz/xds_fuzz_test.go b/test/fuzz/xds_fuzz_test.go
index 1ae498b03..8f769ee6f 100644
--- a/test/fuzz/xds_fuzz_test.go
+++ b/test/fuzz/xds_fuzz_test.go
@@ -7,7 +7,6 @@ package fuzz
 
 import (
 	"testing"
-	"unicode/utf8"
 
 	fuzz "github.com/AdaLogics/go-fuzz-headers"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -73,29 +72,3 @@ func FuzzGatewayClassToXDS(f *testing.F) {
 		_, _ = egctl.TranslateGatewayAPIToXds(namespace, dnsDomain, resourceType, resources)
 	})
 }
-
-// Following code implements a temporary fuzzer to simulate an error to verify OSS-Fuzz integration
-// this test will be removed once the OSS-Fuzz integration is complete
-// This example is based on the Go fuzzing example: https://go.dev/doc/tutorial/fuzz#code_to_test
-// This test should generate errors when the input string is not a valid UTF-8 string
-
-func ReverseStringBugSimulator(s string) string {
-	b := []byte(s)
-	for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 {
-		b[i], b[j] = b[j], b[i]
-	}
-	return string(b)
-}
-
-func FuzzReverseStringBugSimulator(f *testing.F) {
-	f.Fuzz(func(t *testing.T, orig string) {
-		rev := ReverseStringBugSimulator(orig)
-		doubleRev := ReverseStringBugSimulator(rev)
-		if orig != doubleRev {
-			t.Errorf("Before: %q, after: %q", orig, doubleRev)
-		}
-		if utf8.ValidString(orig) && !utf8.ValidString(rev) {
-			t.Errorf("Reverse produced invalid UTF-8 string %q", rev)
-		}
-	})
-}