I recently stumbled on an interesting error coming from an nginx / php-fpm build. A long-running script I was trying to load kept seemingly “timing out” and leaving an empty white screen. There were no errors reported and I was a bit perplexed. I checked all the below:
- max_execution_time set to 0
- max_input_time set to -1
- memory_limit set to 4G
- fastcgi_send_timeout 6000 seconds
- fastcgi_read_timeout 6000 seconds
Even stranger, the only note of the issue in the php / nginx logs was an entry in the nginx log with the HTTP status code 499 – “Client Closed Request.” Initially, I thought my browser was killing the connection after a certain amount of time, but that did not seem to be the case.
Amazon Elastic Load Balancers (AWS ELB)
I realized that this build was running behind an Elastic-Load-Balancer (“ELB”) on the Amazon AWS infrastructure. After poking around, I realized that by default the Load Balancer has an Idle Timeout of 60 seconds. This turned out to be the culprit. As a refresher, the Load Balancer acts as an intermediary between the Client (Browser) and the Server (Host). When the Client requests something from the Server, the Load Balancer opens a connection to both of them, and acts as a messenger for any requests. If the Server doesn’t return something by the Idle Timeout cutoff, the connections are automatically closed.
Since the Load Balancer closes the connection to the Server, NGINX thinks the Client terminated the request (since in this case the ELB *is* the Client).
Luckily the fix is easy, navigate to:
AWS Dashboard -> EC2 -> Load Balancers -> Attributes -> Edit idle timeout
From there, you can set the idle timeout higher.