Using Envoy Gateway for Rate Limiting
Rate limiting is a protection mechanism that controls the rate at which clients send requests to a server. Its core purpose is to prevent system overload from burst traffic and ensure service stability and availability. It is typically expressed as a request quota within a specific time window, for example, 100 requests per minute or 10 requests per second.
Envoy proxies enforce rate limits in two ways: local and global. The key difference is the statistical scope: In local rate limiting, each Envoy instance counts requests independently. In global rate limiting, all Envoy instances share a single request counter. For example, if a Gateway with five Envoy instances is deployed and a rate limit of 100 requests per minute is configured, the effects differ significantly:
- Local rate limiting: Each Envoy instance counts requests independently. Consequently, a Gateway with five Envoy instances can theoretically process up to 500 (5 × 100) requests per minute. This results in significantly higher backend load than intended.
- Global rate limiting: All Envoy instances share a single request counter. Redis serves as a centralized, high-performance distributed counter, enforcing a globally unified quota regardless of which Envoy instance receives the request. This enables precise cross-instance rate limiting. Total traffic is strictly capped at 100 requests per minute, regardless of the number of Envoy instances.
Envoy Gateway supports global rate limiting. When enabled, a rate limiting service is automatically deployed. This service centrally manages global rate limiting policies and real-time traffic data, and enforces rate limits on incoming requests based on the configured policies.
This section provides configuration examples for global and local rate limiting in different scenarios. For complete rate limiting policy parameters, see BackendTrafficPolicy.
Precautions
Before disabling global rate limiting, ensure that all global rate limiting policies have been deleted. Otherwise, route access will fail. For details, see How to Disable Global Rate Limiting?.
Prerequisites
- Envoy Gateway has been installed in the current cluster and is running.
- A backend application and its Service are running in the cluster. In this example, the backend application is Nginx, the Service name is backend, and the Service port is 3000. Save the following YAML as backend.yaml and run kubectl apply -f backend.yaml:
apiVersion: apps/v1 kind: Deployment metadata: name: backend namespace: default spec: replicas: 2 selector: matchLabels: app: backend version: v1 template: metadata: labels: app: backend version: v1 spec: containers: - name: container-1 image: nginx:latest imagePullSecrets: - name: default-secret --- apiVersion: v1 kind: Service metadata: name: backend labels: app: backend version: v1 namespace: default spec: selector: app: backend version: v1 ports: - name: cce-service-0 targetPort: 80 port: 3000 protocol: TCP type: ClusterIP
Creating a Global Rate Limiting Policy
Global rate limiting in Envoy Gateway relies on Redis as a centralized counter to aggregate and enforce real-time traffic quotas across multiple Envoy Gateway instances. This section uses a self-managed Redis service.
Step 1: Deploy Redis
- Use kubectl to access the cluster. For details, see Accessing a Cluster Using kubectl.
- Create redis-service.yaml.
kind: Namespace apiVersion: v1 metadata: name: redis-system --- apiVersion: apps/v1 kind: StatefulSet metadata: name: redis namespace: redis-system labels: app: redis spec: serviceName: "redis" replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - image: redis:latest name: redis ports: - containerPort: 6379 resources: limits: cpu: 1500m memory: 512Mi requests: cpu: 200m memory: 256Mi --- apiVersion: v1 kind: Service metadata: name: redis namespace: redis-system labels: app: redis spec: ports: - name: redis port: 6379 protocol: TCP targetPort: 6379 selector: app: redis - Deploy the Redis service.
kubectl apply -f redis-service.yaml
Step 2: Enable Global Rate Limiting for the Add-on
- Log in to the CCE console and click the cluster name to access the cluster console.
- In the navigation pane, choose Add-ons. On the displayed page, locate Envoy Gateway and click Edit.
- Enable global rate limiting and configure the Redis service address.
In this example, the Redis service in the cluster is accessible at redis.redis-system.svc.cluster.local:6379.

- Click OK.
Step 3: Create a Gateway and an HTTPRoute
Create a Gateway and an HTTPRoute. The rate limiting policies will be applied to this HTTPRoute.
- Create ratelimit.yaml.
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway # Gateway name namespace: default spec: gatewayClassName: envoy-gateway # GatewayClass name listeners: - name: http protocol: HTTP # Protocol port: 80 # Listener port --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute # The resource type is HTTPRoute. metadata: name: ratelimit # HTTPRoute name namespace: default spec: parentRefs: - name: my-gateway # Gateway name hostnames: - "www.example.com" # Domain name rules: - backendRefs: - group: "" kind: Service name: backend # Name of the existing Service port: 3000 # Service port weight: 1 - Deploy the Gateway and HTTPRoute.
kubectl apply -f ratelimit.yaml
Step 4: Create a Rate Limiting Policy (BackendTrafficPolicy)
- Scenario 1: Limiting request frequency
- Scenario 2: Rate limiting for a specific user
- Scenario 3: Rate limiting for all users except a specific one
- Scenario 4: Rate limiting based on client IP addresses (supported only in CCE Turbo clusters using dedicated load balancers)
Creating a Local Rate Limiting Policy
Local rate limiting policies do not depend on Redis. Each Envoy instance counts requests independently.
Step 1: Create a Gateway and an HTTPRoute
Create a Gateway and an HTTPRoute. The rate limiting policies will be applied to this HTTPRoute.
- Create ratelimit.yaml.
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway # Gateway name namespace: default spec: gatewayClassName: envoy-gateway # GatewayClass name listeners: - name: http protocol: HTTP # Protocol port: 80 # Listener port --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute # The resource type is HTTPRoute. metadata: name: ratelimit # HTTPRoute name namespace: default spec: parentRefs: - name: my-gateway # Gateway name hostnames: - "www.example.com" # Domain name rules: - backendRefs: - group: "" kind: Service name: backend # Name of the existing Service port: 3000 # Service port weight: 1 - Deploy the Gateway and HTTPRoute.
kubectl apply -f ratelimit.yaml
Step 2: Create a Rate Limiting Policy (BackendTrafficPolicy)
The scenarios supported by a local rate limiting policy are the same as those supported by a global rate limiting policy. The following example demonstrates how to configure a local rate limiting policy to allow three requests per minute.
- Create backendtrafficpolicy.yaml.
apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: multiple-rules-example namespace: default spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: ratelimit # Name of the HTTPRoute for rate limiting rateLimit: type: Local # Local rate limiting policy local: # Differs from the global rate limiting policy rules: # Rate limiting policy, allowing three requests per minute - limit: requests: 3 unit: Minute - Deploy the rate limiting policy.
kubectl apply -f backendtrafficpolicy.yaml
- Change the number of Envoy pods.
- Log in to the CCE console and click the cluster name to access the cluster console.
- In the navigation pane, choose Add-ons. On the displayed page, locate Envoy Gateway and click Edit.
- Change the number of Envoy pods to 2.
- Click OK.
- Test the request rate limiting.
for i in {1..8}; do curl -I --header "Host: www.example.com" http://xx.xx.xx.xx/ ; sleep 1; doneExpected output:
HTTP/1.1 200 OK server: nginx/1.23.2 date: Sat, 30 May 2026 08:40:34 GMT content-type: text/html content-length: 615 last-modified: Wed, 19 Oct 2022 07:56:21 GMT etag: "634fada5-267" accept-ranges: bytes x-ratelimit-limit: 3 x-ratelimit-remaining: 2 x-ratelimit-reset: 0 HTTP/1.1 200 OK server: nginx/1.23.2 date: Sat, 30 May 2026 08:40:35 GMT content-type: text/html content-length: 615 last-modified: Wed, 19 Oct 2022 07:56:21 GMT etag: "634fada5-267" accept-ranges: bytes x-ratelimit-limit: 3 x-ratelimit-remaining: 2 x-ratelimit-reset: 0 HTTP/1.1 200 OK server: nginx/1.23.2 date: Sat, 30 May 2026 08:40:36 GMT content-type: text/html content-length: 615 last-modified: Wed, 19 Oct 2022 07:56:21 GMT etag: "634fada5-267" accept-ranges: bytes x-ratelimit-limit: 3 x-ratelimit-remaining: 1 x-ratelimit-reset: 0 HTTP/1.1 200 OK server: nginx/1.23.2 date: Sat, 30 May 2026 08:40:37 GMT content-type: text/html content-length: 615 last-modified: Wed, 19 Oct 2022 07:56:21 GMT etag: "634fada5-267" accept-ranges: bytes x-ratelimit-limit: 3 x-ratelimit-remaining: 1 x-ratelimit-reset: 0 HTTP/1.1 200 OK server: nginx/1.23.2 date: Sat, 30 May 2026 08:40:38 GMT content-type: text/html content-length: 615 last-modified: Wed, 19 Oct 2022 07:56:21 GMT etag: "634fada5-267" accept-ranges: bytes x-ratelimit-limit: 3 x-ratelimit-remaining: 0 x-ratelimit-reset: 15 HTTP/1.1 200 OK server: nginx/1.23.2 date: Sat, 30 May 2026 08:40:39 GMT content-type: text/html content-length: 615 last-modified: Wed, 19 Oct 2022 07:56:21 GMT etag: "634fada5-267" accept-ranges: bytes x-ratelimit-limit: 3 x-ratelimit-remaining: 0 x-ratelimit-reset: 15 HTTP/1.1 429 Too Many Requests content-length: 18 content-type: text/plain x-ratelimit-limit: 3 x-ratelimit-remaining: 0 x-ratelimit-reset: 13 date: Sat, 30 May 2026 08:40:40 GMT HTTP/1.1 429 Too Many Requests content-length: 18 content-type: text/plain x-ratelimit-limit: 3 x-ratelimit-remaining: 0 x-ratelimit-reset: 13 date: Sat, 30 May 2026 08:40:41 GMT
The command output shows that HTTP 200 is returned for the first six requests and HTTP 429 for the seventh and eighth requests, indicating that each of the two Envoy instances allows three requests per minute, for a total of six. The local rate limiting policy is effective.
FAQs
How to Disable Global Rate Limiting?
Before disabling global rate limiting, ensure that all global rate limiting policies have been deleted or converted to local rate limiting policies. To do this, perform the following steps:
- Check global rate limiting policies.
kubectl get backendtrafficpolicy -A -o jsonpath='{range .items[?(@.spec.rateLimit.type=="Global")]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}' - Delete these policies or convert them to local ones. The following example converts a global rate limiting policy to a local one:
apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: multiple-rules-example namespace: default spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: ratelimit rateLimit: type: Global # Convert it to a local one. global: # Change it to local. rules: - limit: requests: 3 unit: Minute - Repeat step 1 to verify the change.
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot
