Rate Limiting In Nginx

Christopher Phillips
2 min readNov 20, 2018

--

Hello and welcome to my latest challenge, 3 posts a week based on interesting topics I have learnt whilst working in the Finnish startup scene!

Today, rate limiting in NGINX.

Why?

In production you can be subject to DDos attacks to your server which can overload RAM/CPU/I/O so you must seek to limit the number of requests per IP.

How?

Nginx has a default module to setup rate limiting.

Here’s how to use it.

  1. Add a new limit configuration to the top of your nginx config.
limit_req_zone $binary_remote_addr zone=basic_limit:10m rate=3r/s;

Lets break it down:

$binary_remote_addr

Our reference to the binary IP address of each user

zone=basic_limit:10m

Our shared memory zone which will keep the IP addresses in memory with a cap of 10mb (can store 16,000 addresses to 1mb — so 160,000 here :) )

rate=3r/s;

Our rate per given time period. Here is it 3 per second. We could also have per minute e.t.c.

2. Decided where you want to use the rate limiting — which resources or locations.

For my app I wanted to use it for all routes except for static files folders so I had two location blocks setup, one for /static which did not have any rate limiting, and one for all other requests on / route. Here it is:

location ~ ^/(static|images) {   proxy_pass http://localhost:3002;}location / {   limit_req zone=basic_limit burst=5;   proxy_pass http://localhost:3002;}

So we have limit_req enabled in the / route. Again, lets break it down:

zone=basic_limit

Choose which memory zone we want — here we only have one but you might want tracking of IPS in different memory zones for different resources.

burst=5

Given that we might want to allow more requests at any given time — this will allow a temporary burst of 5 more requests per time period at an interval of 100ms each. If you want to have this interval reduced so it happens automatically (useful for serving js/css/images quickly to your frontend) you can also remove the delay like so:

burst=5 nodelay;

So our full config comes to the following:

limit_req_zone $binary_remote_addr zone=basic_limit:10m rate=3r/s;location ~ ^/(static|images) {   proxy_pass http://localhost:3002;}location / {   limit_req zone=basic_limit burst=5;    proxy_pass http://localhost:3002;}

This will limit each IP address to 3 requests per second, allowing 5 queued requests per second if needed at times of high load.

For us this was perfect because we didn’t want to limit requests for static files but only to our frontend rendering server on our main routes because server side rendering is somewhat costly! :)

We will probably update this and make it far more secure as we scale higher and higher ;)

--

--

Christopher Phillips

Full stack web dev and mountain runner, Manchester -> <- Helsinki