When implementing HAProxy with multiple backend servers, you might need a fallback server that consistently returns HTTP 503 (Service Unavailable) status. This is particularly useful when all backend servers are down, and you want to explicitly signal unavailability rather than serving stale content or connection errors.
The simplest way to force 503 responses is to configure a server block that returns this status for all requests:
server {
listen 80;
server_name fallback.example.com;
location / {
return 503;
}
error_page 503 /503.html;
location = /503.html {
internal;
root /usr/share/nginx/html;
}
}
For better user experience, you might want to serve a custom error page while maintaining the 503 status:
server {
listen 80 default_server;
location / {
return 503;
# Optional: add maintenance message
add_header Retry-After 3600;
}
error_page 503 /maintenance.html;
location = /maintenance.html {
root /var/www/html;
internal;
}
}
To ensure all HTTP methods (GET, POST, etc.) receive 503 responses:
server {
listen 80;
location / {
if ($request_method) {
return 503;
}
}
}
When using this as a fallback server in HAProxy, consider these optimizations:
server {
listen 80 reuseport;
server_name _;
access_log off;
error_log /dev/null crit;
location / {
return 503;
}
}
After implementing, verify with curl:
curl -I http://your-nginx-server
HTTP/1.1 503 Service Unavailable
Server: nginx/1.18.0
Content-Type: text/html
Connection: keep-alive
In your HAProxy configuration, reference this Nginx instance as a backup:
backend app_cluster
balance roundrobin
server app1 10.0.0.1:80 check
server app2 10.0.0.2:80 check
server fallback 10.0.0.3:80 backup
When building high-availability systems with HAProxy, you sometimes need a designated "backup" server that intentionally returns 503 (Service Unavailable) responses. This becomes particularly useful when:
- All backend servers are down
- You want to prevent HAProxy from marking the backup server as available
- You need a maintenance mode endpoint
Create a dedicated server block that returns 503 for all requests:
server {
listen 80;
server_name backup.example.com;
location / {
return 503;
}
error_page 503 /503.html;
location = /503.html {
internal;
root /usr/share/nginx/html;
}
}
For more control over the behavior:
server {
listen 80 default_server;
server_name _;
# Return 503 for all requests
location / {
return 503;
add_header Retry-After 3600;
}
# Custom error page handling
error_page 503 @maintenance;
location @maintenance {
internal;
add_header Content-Type text/html;
return 503 "<html><body><h1>Service Unavailable</h1></body></html>";
}
# Prevent logging these requests
access_log off;
}
In your HAProxy configuration, reference this Nginx instance as a backup:
backend app_cluster
balance roundrobin
option httpchk GET /health
server app1 192.168.1.10:80 check
server app2 192.168.1.11:80 check
server backup 192.168.1.12:80 check backup
Verify your setup works correctly:
curl -v http://backup.example.com
# Should return:
# HTTP/1.1 503 Service Unavailable
# Server: nginx/1.18.0
# ...
Since this Nginx instance won't process any real requests, you can optimize it:
- Disable access logging completely
- Set worker_processes to 1
- Reduce worker_connections to minimal value