Keep Nginx startup independent of upstream DNS availability
Avoid configuration-time hostname failures with runtime resolution, understand backup limits, and return a controlled maintenance response.
A hostname in a static upstream configuration is normally resolved when Nginx loads that configuration. If resolution fails, a new instance may refuse to start with host not found in upstream. On reload, the existing master normally retains the old working configuration instead.
Use runtime resolution when temporary backend DNS failure should affect requests without preventing the proxy from starting.
Resolve a variable-based target at request time
server {
listen 80;
location / {
# Replace this example address with your trusted DNS server.
resolver 10.0.0.53 valid=30s;
resolver_timeout 5s;
set $backend backend.example.com;
proxy_pass http://$backend;
}
}
This defers resolution for that target. If DNS is unavailable, affected requests can fail with 502; it does not make the backend available. Other configuration errors or unresolved static hostnames elsewhere can still prevent startup.
The runtime resolver caches answers. valid=30s overrides the returned TTL; it does not perform a lookup for every request. For private container or cluster names, use a resolver reachable from Nginx's network namespace that knows those names.
Use dynamic upstream groups where supported
Open-source Nginx 1.27.3 and later support this alternative inside http:
upstream backend {
zone backend 64k;
resolver 10.0.0.53 valid=30s;
server backend.example.com:8080 resolve;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
Earlier open-source versions need another approach such as variable proxy_pass; resolve was previously commercial-only. Confirm the installed version and test the DNS-unavailable startup case in staging.
Know what a backup does and does not solve
upstream backend {
server 10.0.0.11:8080;
server 10.0.0.12:8080;
server 127.0.0.1:8080 backup;
}
Literal IP addresses avoid hostname resolution for those members. A backup can handle requests when the primary members are unavailable, but it must be a real service in the same network namespace. Adding a backup does not make an unresolvable static hostname elsewhere in the group acceptable at configuration load time. Pinning service IPs also creates address-maintenance work.
Return an explicit maintenance response
Inside the existing proxied location, add error interception and a named fallback:
location / {
proxy_pass http://backend;
proxy_intercept_errors on;
error_page 502 503 504 = @fallback;
}
location @fallback {
default_type text/plain;
add_header Retry-After 60 always;
return 503 "Service temporarily unavailable. Please try again later.\n";
}
This also intercepts selected error responses returned by the backend. Keep the actual error status and log the original failure for diagnosis. A fallback cannot help if the configuration never loads.
FAQ
Which option fits a Kubernetes Service or cloud load-balancer hostname?
Use a supported dynamic upstream group or runtime variable resolution with the appropriate private DNS. Verify readiness separately; an existing DNS name does not guarantee healthy endpoints.
Can I use arbitrary variables in an upstream server directive?
Do not assume general variable interpolation is supported there. Dynamic DNS with resolve is a specific feature, not arbitrary per-request substitution.
Should orchestration ordering solve this instead?
It can help when startup readiness is a real dependency. For Compose, startup ordering alone differs from health-based readiness. Runtime resolution is useful when the proxy should remain available while a backend changes or recovers.
References: upstream resolve and backup, proxy error interception, reload behavior.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan