If you're proxying from nginx to an ELB endpoint, either CNAME or a DNS entry, you'd most likely end up in an issue where nginx sometimes sends the requests to an unknown IP.

Below is an example config of nginx proxy passing to an ELB when it receives a request for /api/:

upstream ghost {
    server NameOfElb.us-east-1.elb.amazonaws.com;
}

server {
    listen 80;
    server_name acsrujan.net;
    location /api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header HOST $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://ghost;
        proxy_redirect off;
        }
}

With above config, nginx resolves IP when it starts and caches it.

Nginx respects DNS TTLs. AWS keeps indefinite TTL for ELB DNS

Fix

Fortunately, this is simple to fix. Just add a line to server block or http block. This will ensure DNS resolves every often.

server {
    resolver 172.16.0.23; #the ip here is default dns resolver for AWS.
}

Edit:

  1. Make sure to append $requesturi at proxy_pass proxy_pass http://ghost becomes proxy_pass http://ghost$request_uri
    Nginx caches dns if request uri isn't there.

  2. For DNS other than ELBs where such use case comes up and you don't have resolver to look for, you can add resolver 127.0.0.1 valid=300s which forces dns lookup every 5 minutes (if there are requests).

Why does ELB IP change?

AWS scales up/down, replaces instances used for ELB as and when required. They keep it agnostic to the users by updating DNS in their system. They keep previous as well as new IPs intact for a short period of time, letting dns to re-resolve to latest IP.