Nginx – How to prevent nginx throttling conflicting with maintenance mode

maintenancenginxrate-limitingthrottling

We use the HttpLimitReqModule nginx mondule for rate throttling and have found that it conflicts with our "maintenance mode" because both components are using http status code 503.

When throttling is activated (via the limit_req directive), nginx would normally serve a 503, but unfortunatly our maintenance mode location is used, which results in a 302 to our Amazon S3 hosted maintenance page. A 302 for a throttled request is not a good outcome.

I was wondering how other people deal with this issue? Should I for example use a different status code for our maintenance page, but if so, what?

Ideally for throttled requests, I don't want any page served, only a 503 response header – it needs to be as lightweight as possible because the whole point is to stop the server being overwhelmed.


For reference, this is the nginx config that we use for "Maintenance Mode":

server {
    ...

    # Redirect processing of 503 error pages into a named location:
    error_page 503 @maintenance;

    # "Maintenance Mode" is off by default - Use a nginx variable to track state.
    set $maintenance off;

    # Switch on "Maintenance Mode" if a certain file exists.
    if (-f /var/www/mysite/shared/maintenanceON) {
        set $maintenance on;
    }

    if ($maintenance = on) {
        return 503; # 503 - Service unavailable
    }

    location @maintenance {
        # Redirect the request to our maintenance page in Amazon S3.
        rewrite ^(.*)$ http://mysite.s3-website-us-east-1.amazonaws.com/ break;
    }
    ...
    # Process the php files - pass to php-fpm.
    location ~ \.php {
        # Limit aggressive bots and crawlers to 30 requests per minute.
        limit_req zone=bots;

        fastcgi_pass 127.0.0.1:$fastcgi_port;
    }
    ...

Best Answer

Use a status code other than 503 for your "maintenance mode."

As we can clearly see, users don't actually get served a 503 when you are using "maintenance mode" anyway, so there's no benefit to using that status code internally in your configuration. Make up another code (593?) and use that.


Or better yet, skip the extra location and just send the rewrite directly when the maintenance file exists.

    if (-f /var/www/mysite/shared/maintenanceON) {
        rewrite ^(.*)$ http://mysite.s3-website-us-east-1.amazonaws.com/ redirect;
    }