Nginx – How to stop nginx from retrying PUT or POST requests on upstream server timeout

nginxreverse-proxy

We are using nginx to load balance requests to our application. We have found that nginx switches to a different upstream server when requests time out (good). However it does this for PUT and POST requests which can cause undesirable results (data stored twice). Is it possible to configure nginx to only retry GET requests on timeout? Or is there another way to solve the problem?

Our configuration is as follows:

upstream mash {
    ip_hash;
    server 127.0.0.1:8081;
    server 192.168.0.11:8081;
}

server {
    ...
    location / {
        proxy_pass http://mash/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        
    }
}

Best Answer

Starting in nginx 1.9.13, non-idempotent requests (PUT, POST, etc) are not retried by default. If you can upgrade to this version of later, you can obtain the desired behavior by default.

If for some reason you would like to continue retrying PUT, POST, etc (non-idempotent) requests on 1.9.13 or later, use:

proxy_next_upstream error timeout non_idempotent;