How To Limit Rate of Connections (Requests) in NGINX

In our last article which is part of our NGINX traffic management series, we discussed how to limit the number of connections in NGINX. In this guide, we will look at how to limit the rate of requests in NGINX.

Rate limiting is a traffic management technique used to restrict the number of HTTP requests a client can make in a given period of time – rate limits are calculated in Requests Per Second (or RPS).

An example of a request is a GET request for the log-in page of an application or a POST request on a log-in form or a POST on an API endpoint.

There are many reasons to limit the rate of requests to your web applications or API services, one being security: protecting against abusive rapid requests.

Limiting Rate of Connections in NGINX

Start by defining the parameters for rate-limiting using the limit_req_zone directive. The required parameters are a key for identifying clients, a shared memory zone that will store the state of the key and how often it has accessed a request-restricted URL, and the rate.

The limit_req_zone directive is valid within the HTTP context.

limit_req_zone $binary_remote_addr zone=limitreqsbyaddr:20m rate=10r/s;

Also, set a response status code that is returned to rejected requests, using the limit_req_status directive which is valid within the HTTP, sever, and location contexts.

limit_req_status 429;

Now you can use the limint_conn directive to enable request rate-limiting within the HTTP, sever, and location contexts. It takes a memory zone as a parameter and other optional parameters.

limit_req zone=limitreqsbyaddr;

The following configuration example shows limiting the rate of request to a web application API. The shared memory size is 20 MB and the request rate limit is 10 requests per second.

upstream api_service {
    server 127.0.0.1:9051;
    server 10.1.1.77:9052;
}
limit_req_zone $binary_remote_addr zone=limitreqsbyaddr:20m rate=10r/s;
limit_req_status 429;

server {
    listen 80;
    server_name testapp.tecmint.com;
    root /var/www/html/testapp.tecmint.com/build;
    index index.html;

    #include snippets/error_pages.conf;
    proxy_read_timeout 600;
    proxy_connect_timeout 600;
    proxy_send_timeout 600;
    location / {
        try_files $uri $uri/ /index.html =404 =403 =500;
    }
    location /api {
        limit_req zone=limitreqsbyaddr;
        proxy_pass http://api_service;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

       
   }
}

Save your configuration file and close it.

Then check if the NGINX configuration syntax is correct using the following command:

$ sudo nginx -t

After that, reload the NGINX service apply the latest changes:

$ sudo systemctl reload nginx

Once the rate limit of 10 requests per second is exceeded by a single client accessing /api/, NGINX returns a “429 Too many requests” error to the client.

Nginx 429 Too many requests Error
Nginx 429 Too many requests Error

It also logs the incident in the error log.

2022/04/29 00:30:38 [error] 3145846#0: *131039 limiting requests, excess: 0.990 by zone "limitreqsbyaddr", client: 192.168.1.10, server: testapp.tecmint.com, request: "GET /api/v1/app/meta-data HTTP/1.1", host: "testapp.tecmint.com", referrer: "https://testapp.tecmint.com/"
Nginx Error Logs
Nginx Error Logs

Sometimes depending on the nature of your application or API, a client will need to make many requests all at once, and then reduce its rate for a period of time before making more. NGINX can also buffer any excess requests in a queue and process them promptly.

You can enable this behavior in rate-limiting using the burst parameter with the limit_req directive. To enable queueing with no delay, add the nodelay parameter.

limit_req zone=limitreqsbyaddr burst=20 nodelay;

There is a snag with rate limiting based on a client’s IP, particularly for users accessing your application from the same network and operating behind a NAT. In this case, all their requests will originate from the same IP address. In such a scenario, you can use other variables to identify clients such as a session cookie.

For more information on limiting the rate of requests, check out this NGINX rate limiting on the NGINX website. Next, we shall cover how to limit bandwidth usage in NGINX.

Hey TecMint readers,

Exciting news! Every month, our top blog commenters will have the chance to win fantastic rewards, like free Linux eBooks such as RHCE, RHCSA, LFCS, Learn Linux, and Awk, each worth $20!

Learn more about the contest and stand a chance to win by sharing your thoughts below!

Aaron Kili
Aaron Kili is a Linux and F.O.S.S enthusiast, an upcoming Linux SysAdmin, web developer, and currently a content creator for TecMint who loves working with computers and strongly believes in sharing knowledge.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

3 Comments

Leave a Reply
  1. There is an unfortunate little mistake in the configs. In "location /api" the zone name should be limit_req zone=limitreqsbyaddr;
    not limit_req zone=limitregsbyaddr;

    (regs => reqs)

    Reply
  2. Hello,

    There’s a type in the example config

    limit_req zone=limitregsbyaddr; 
    

    should be limitre'Q'sbyaddr.

    Thanks for sharing!

    Reply

Got Something to Say? Join the Discussion...

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.