Proxy timeouts decide how long Apache waits for a backend to accept a connection or return data, which determines whether slow upstream work completes cleanly or turns into premature 502 Bad Gateway or 504 Gateway Timeout failures.
When Apache reverse proxies requests through mod_proxy, the global Timeout directive remains the base fallback, ProxyTimeout sets the default proxy socket timeout, connectiontimeout limits how long backend connection setup may take, and timeout on a direct worker controls how long Apache waits for data to flow after the connection is established.
Long proxy timeouts can keep workers occupied during upstream stalls and reduce concurrency, so raise them only to match measured application behavior. Examples below use the Debian / Ubuntu layout under /etc/apache2/ with the apache2 service; on RHEL-family systems the configuration usually lives under /etc/httpd/ and the service name is httpd.
$ sudo apache2ctl -S
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 203.0.113.10. Set the 'ServerName' directive globally to suppress this message
VirtualHost configuration:
*:80 is a NameVirtualHost
default server 203.0.113.10 (/etc/apache2/sites-enabled/000-default.conf:1)
port 80 namevhost 203.0.113.10 (/etc/apache2/sites-enabled/000-default.conf:1)
port 80 namevhost proxy.example.net (/etc/apache2/sites-enabled/proxy.example.net.conf:1)
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www/html"
##### snipped #####
Use the matching /etc/httpd/conf.d/ or vhost file on RHEL-family systems if the site is not under /etc/apache2/sites-available.
$ sudo cp -a /etc/apache2/sites-available/proxy.example.net.conf /etc/apache2/sites-available/proxy.example.net.conf.bak
$ sudo a2enmod proxy proxy_http Module proxy already enabled Considering dependency proxy for proxy_http: Module proxy already enabled Module proxy_http already enabled
Add proxy_balancer plus the needed lbmethod_* module when the site proxies to balancer:// URLs instead of a single backend.
$ sudoedit /etc/apache2/sites-available/proxy.example.net.conf
ProxyTimeout 120
| Setting | Scope | What it limits |
|---|---|---|
| Timeout | global or VirtualHost | Base timeout for several core operations and the fallback value when ProxyTimeout is unset. |
| ProxyTimeout | server config or VirtualHost | Default socket timeout for proxied requests. |
| connectiontimeout | direct ProxyPass worker or BalancerMember | Time allowed to establish the backend TCP connection. |
| timeout | direct ProxyPass worker or BalancerMember | Time allowed for data to be sent to or read from the backend after the connection is open. |
ProxyPass timeout=… overrides ProxyTimeout only for direct backend workers such as http://127.0.0.1:8080 mappings.
ProxyPass "/app/" "http://127.0.0.1:8080/app/" connectiontimeout=5 timeout=120 ProxyPassReverse "/app/" "http://127.0.0.1:8080/app/" ProxyPass "/reports/" "http://127.0.0.1:8080/reports/" connectiontimeout=5 timeout=600 ProxyPassReverse "/reports/" "http://127.0.0.1:8080/reports/"
Keep longer and more specific ProxyPass paths above shorter catch-all paths because Apache evaluates the rules in configuration order and the first match wins.
If backend worker URLs overlap, Apache can reuse the first worker and silently ignore later per-worker timeout values, so re-check warnings from apache2ctl -t after reordering similar mappings.
BalancerMember "http://node-01:8080" connectiontimeout=5 timeout=120 BalancerMember "http://node-02:8080" connectiontimeout=5 timeout=120 ProxySet lbmethod=byrequests # keep the public mapping lines outside the balancer member block ProxyPass "/app/" "balancer://appcluster/app/" ProxyPassReverse "/app/" "balancer://appcluster/app/"
On a balancer:// target, the timeout key on ProxyPass refers to balancer worker wait time, not backend socket I/O timeout, so keep the backend timeout on each BalancerMember.
$ sudo grep --line-number --extended-regexp 'ProxyTimeout|ProxyPass|BalancerMember' /etc/apache2/sites-available/proxy.example.net.conf 5: ProxyTimeout 120 7: ProxyPass "/app/" "http://127.0.0.1:8080/app/" connectiontimeout=5 timeout=120 11: BalancerMember "http://node-01:8080" connectiontimeout=5 timeout=120 12: BalancerMember "http://node-02:8080" connectiontimeout=5 timeout=120
Seeing the timeout on BalancerMember instead of the load-balancer ProxyPass line avoids the common timeout mix-up.
$ sudo apache2ctl -t Syntax OK
The AH00558 global ServerName warning can still appear before Syntax OK on fresh installs and does not invalidate the test result.
Related: How to test Apache configuration
$ sudo systemctl reload apache2
Use sudo systemctl reload httpd on most RHEL-family systems.
$ curl --silent --show-error -i http://proxy.example.net/reports/daily.json
HTTP/1.1 200 OK
Date: Thu, 09 Apr 2026 12:54:05 GMT
Server: Apache/2.4.58 (Ubuntu)
Content-Type: application/json
Content-Length: 32
{"status":"ok","report":"daily"}
If a local loopback request does not hit the same virtual host, use the public hostname directly or add a Host header that matches the vhost you tuned.
LogLevel warn proxy:info proxy_http:info
Verbose proxy logging can grow /var/log/apache2/error.log quickly on busy hosts, so revert the extra module log levels after the failure is captured.