> ## Documentation Index
> Fetch the complete documentation index at: https://qovery-docs-agent-console-2026-09-29.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Setup Rate Limit on Services

> Configure rate limiting for services using NGINX

This guide covers implementing rate limits on Qovery services through NGINX customization. Rate limiting helps protect services from abuse. While third-party solutions like Cloudflare are recommended for filtering traffic before it reaches workloads, this tutorial demonstrates cluster-level implementation.

<Warning>
  Changing NGINX snippets configuration is an advanced feature and can lead to misconfiguration. Please be careful when changing these settings as it might break the whole NGINX configuration.
</Warning>

## Prerequisites

* Application running on a Qovery managed cluster
* Basic understanding of NGINX rate limiting

## Understanding NGINX Rate Limiting

NGINX rate limiting protects your services by controlling the rate of requests. For detailed information, see [NGINX's official documentation on rate limiting](https://www.nginx.com/blog/rate-limiting-nginx/).

***

## Initial Setup

### Configure Test Service

We'll use `jmalloc/echo-server` Docker image for testing:

* Image: `jmalloc/echo-server`
* Port: 80

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/service-initial-setup-qovery-screen.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=b110b39274319041bf665cad68f7fff9" alt="Service initial setup" width="1211" height="315" data-path="images/nginx-rate-limit/service-initial-setup-qovery-screen.png" />
</Frame>

### Configure NGINX Replicas

Rate limits apply per NGINX instance. For demonstration, set replicas to 1 (not recommended for production):

1. Go to **Cluster Settings** → **Advanced Settings**
2. Find `nginx.controller.replicas`
3. Set value to `1`

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/cluster-advanced-settings-replicas.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=4cecc0d6419e693ef2405f10d1104e22" alt="Set NGINX replicas" width="814" height="102" data-path="images/nginx-rate-limit/cluster-advanced-settings-replicas.png" />
</Frame>

<Info>
  Without rate limits: 100 req/sec × 500 requests = 100% success rate (all HTTP 200 responses)
</Info>

***

## Global Rate Limit Implementation

### Declare at Cluster Level

Configure `nginx.controller.http_snippet`:

```nginx theme={null}
limit_req_zone "$server_name" zone=global:10m rate=10r/s;
```

**Components:**

* `$server_name`: Rate limit key (can use `$http_x_forwarded_for` for IP-based limits)
* `zone=global:10m`: Zone name with 10MB memory allocation
* `rate=10r/s`: 10 requests per second threshold

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/cluster-advanced-settings-set-global-rate-in-http-snippet.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=0724c0c362827c8cb00d71f451b6060c" alt="Set global rate in http snippet" width="1245" height="691" data-path="images/nginx-rate-limit/cluster-advanced-settings-set-global-rate-in-http-snippet.png" />
</Frame>

### Apply Rate Limit

Configure `nginx.controller.server_snippet`:

```nginx theme={null}
location / {
    limit_req zone=global;
}
```

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/cluster-advanced-settings-set-global-rate-in-server-snippet.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=9e4ab6c6e33c83e6f91c3876959445cd" alt="Apply global rate in server snippet" width="1272" height="663" data-path="images/nginx-rate-limit/cluster-advanced-settings-set-global-rate-in-server-snippet.png" />
</Frame>

### Deploy Changes

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/deploy-cluster-after-advanced-settings-changes.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=6f6c241998f40b927c996ef4387c145b" alt="Deploy cluster changes" width="1272" height="551" data-path="images/nginx-rate-limit/deploy-cluster-after-advanced-settings-changes.png" />
</Frame>

### Enhancement with Burst

Adding `burst=20 nodelay;` permits 20-request bursts without delays:

```nginx theme={null}
location / {
    limit_req zone=global burst=20 nodelay;
}
```

### Test Results

Load test: 100 req/sec for 500 total requests

**Result:**

* 452 HTTP 503 rejections
* 48 HTTP 200 acceptances (\~9.6 req/sec)

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/nginx-logs-rejecting-requests-with-global-rate.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=672fd6bca497a005af3eb62faab60b7a" alt="Global rate limit logs" width="1268" height="627" data-path="images/nginx-rate-limit/nginx-logs-rejecting-requests-with-global-rate.png" />
</Frame>

***

## Service-Level Rate Limit

Configure rate limiting at the service level using advanced settings:

**Configuration Settings:**

* `network.ingress.nginx_limit_rps`: Rate in requests/second
* `network.ingress.nginx_limit_rpm`: Rate in requests/minute
* `network.ingress.nginx_limit_burst_multiplier`: Burst multiplier (default: 5)

### Example: 10 Requests/Minute with 2× Burst

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/service-advanced-settings-set-limit-rpm-and-burst.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=d98ed3bef95a441091b35696d1af595c" alt="Service-level rate limit" width="1277" height="661" data-path="images/nginx-rate-limit/service-advanced-settings-set-limit-rpm-and-burst.png" />
</Frame>

<Info>
  When both RPM and RPS are set, both rate limits will be enforced simultaneously. Traffic will be restricted based on whichever limit is hit first.
</Info>

### Deploy Service

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/deploy-service.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=42e2143c7078d445d94c5badd7e7af8f" alt="Deploy service with rate limit" width="1275" height="643" data-path="images/nginx-rate-limit/deploy-service.png" />
</Frame>

### Test Results

* 479 HTTP 503 rejections
* 21 HTTP 200 acceptances

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/nginx-logs-rejecting-requests-with-service-rate.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=f3d75e53f66d6bc5191668a8aa6a5cf2" alt="Service rate limit logs" width="1272" height="694" data-path="images/nginx-rate-limit/nginx-logs-rejecting-requests-with-service-rate.png" />
</Frame>

***

## Custom Header-Based Rate Limiting

Implement rate limiting based on custom HTTP headers.

### Cluster Configuration

Configure `nginx.controller.http_snippet`:

```nginx theme={null}
map $http_x_qovery_api_key $limit_key {
    default $http_x_qovery_api_key;
    "" "anonymous";
}

limit_req_zone $limit_key zone=qovery_api_limit:10m rate=5r/s;
```

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/cluster-advanced-settings-set-custom-header-rate-in-http-snippet.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=8646c3f6a63c6d7b4f03b844025a62d0" alt="Custom header rate limit declaration" width="3410" height="1320" data-path="images/nginx-rate-limit/cluster-advanced-settings-set-custom-header-rate-in-http-snippet.png" />
</Frame>

**Details:** Maps HTTP header values to rate limit keys; missing headers default to "anonymous" designation.

### Service Configuration

Configure `network.ingress.nginx_controller_configuration_snippet`:

```nginx theme={null}
limit_req zone=qovery_api_limit burst=2 nodelay;
```

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/service-advanced-settings-set-customer-header-rate-limiter-in-configuration-snippet.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=b1261ad43b804cc9fc1118f0b7693111" alt="Apply custom header rate limit" width="3410" height="946" data-path="images/nginx-rate-limit/service-advanced-settings-set-customer-header-rate-limiter-in-configuration-snippet.png" />
</Frame>

**Burst Parameter Explanation:**

* `burst=2`: Permits 2 extra requests beyond rate limit during short bursts
* `nodelay`: Disables request queuing; excess requests rejected immediately

### Deploy and Test

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/deploy-service-with-custom-header-rate-limiter.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=59ea4412b020d5ec7623f0f0cc477a1b" alt="Deploy with custom header rate limit" width="3418" height="1302" data-path="images/nginx-rate-limit/deploy-service-with-custom-header-rate-limiter.png" />
</Frame>

**Test Command:**

```bash theme={null}
oha -q 100 -n 500 -H "X-QOVERY-API-KEY: benjamin"
```

**Result:**

* 473 HTTP 503 rejections
* 27 HTTP 200 acceptances (\~5.4 req/sec with burst)

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/nginx-logs-rejecting-requests-with-custom-header-in-service-logs.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=3924f96d9b0b691a1f669cd6389dcb43" alt="Service logs with custom header" width="1273" height="703" data-path="images/nginx-rate-limit/nginx-logs-rejecting-requests-with-custom-header-in-service-logs.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/nginx-logs-rejecting-requests-with-custom-header.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=eeaa9928015d4f3e2f0dd1989974fea5" alt="NGINX logs with custom header" width="1240" height="127" data-path="images/nginx-rate-limit/nginx-logs-rejecting-requests-with-custom-header.png" />
</Frame>

***

## Additional Configuration

### Custom HTTP Status Code

Configure `nginx.controller.limit_request_status_code`:

* Default: HTTP 503
* Alternative: HTTP 429 (commonly used for rate limiting)

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/cluster-advanced-settings-custom-limit-http-status.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=2c2df786ea8fb85164d34656f241dbe6" alt="Custom HTTP status code" width="1276" height="577" data-path="images/nginx-rate-limit/cluster-advanced-settings-custom-limit-http-status.png" />
</Frame>

Test results show HTTP 429 responses:

<Frame>
  <img src="https://mintcdn.com/qovery-docs-agent-console-2026-09-29/eRiEwZM0u2kOTjuM/images/nginx-rate-limit/cluster-advanced-settings-custom-limit-http-status-logs.png?fit=max&auto=format&n=eRiEwZM0u2kOTjuM&q=85&s=c76b978f5cbc2b932a4e4d21f08448c3" alt="HTTP 429 response logs" width="3394" height="608" data-path="images/nginx-rate-limit/cluster-advanced-settings-custom-limit-http-status-logs.png" />
</Frame>

### Connection Limits

Configure `network.ingress.nginx_limit_connections` at service level to limit concurrent connections from single IP addresses.

***

## Summary

<AccordionGroup>
  <Accordion title="Global Rate Limit">
    Applied at cluster level, affects all services. Best for protecting the entire cluster from abuse.
  </Accordion>

  <Accordion title="Service-Level Rate Limit">
    Applied per service using `nginx_limit_rps` or `nginx_limit_rpm`. Best for protecting individual services.
  </Accordion>

  <Accordion title="Header-Based Rate Limit">
    Applied based on custom HTTP headers. Best for API key-based rate limiting and multi-tenant applications.
  </Accordion>

  <Accordion title="Connection Limits">
    Limits concurrent connections per IP. Best for preventing connection exhaustion attacks.
  </Accordion>
</AccordionGroup>

***

## Related Documentation

<CardGroup cols={2}>
  <Card title="Advanced Settings" icon="sliders" href="/configuration/service-advanced-settings">
    Configure service advanced settings
  </Card>

  <Card title="NGINX Configuration" icon="server" href="/configuration/integrations/api-gateway-nginx">
    Learn about NGINX ingress
  </Card>

  <Card title="Cluster Configuration" icon="layer-group" href="/configuration/clusters">
    Configure cluster settings
  </Card>

  <Card title="Security Best Practices" icon="shield" href="/getting-started/security-and-compliance/overview">
    Implement security measures
  </Card>
</CardGroup>
