Introduction

When Apache's MaxRequestWorkers limit is reached, the server stops accepting new connections and returns 503 Service Unavailable to clients. The error log records:

bash
[Mon Apr 08 20:30:15.123456 2026] [mpm_prefork:error] [pid 1234] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting

This occurs when concurrent requests exceed the configured worker capacity, often during traffic spikes or when requests are held open by slow backend processing.

Symptoms

  • Clients receive 503 Service Unavailable responses
  • Apache error log shows "server reached MaxRequestWorkers setting"
  • apachectl status shows all worker slots as "W" (writing response) or "K" (keepalive)
  • New connections queue and eventually time out
  • Server appears to stop responding while existing requests are still processing

Common Causes

  • MaxRequestWorkers set too low for actual traffic volume
  • Slow PHP or application responses holding worker slots open for extended periods
  • KeepAlive connections occupying worker slots while idle
  • Memory limit per Apache process restricting how high MaxRequestWorkers can be set
  • No connection queuing mechanism, requests are dropped immediately when limit is reached

Step-by-Step Fix

  1. 1.Check current Apache MPM configuration:
  2. 2.```bash
  3. 3.apachectl -V | grep -i mpm
  4. 4.sudo apachectl status --no-pager | head -40
  5. 5.`
  6. 6.Identify whether you are using mpm_prefork, mpm_worker, or mpm_event.
  7. 7.Increase MaxRequestWorkers in the appropriate MPM configuration. For event MPM at /etc/apache2/mods-available/mpm_event.conf:
  8. 8.```apache
  9. 9.<IfModule mpm_event_module>
  10. 10.StartServers 4
  11. 11.MinSpareThreads 25
  12. 12.MaxSpareThreads 75
  13. 13.ThreadLimit 64
  14. 14.ThreadsPerChild 25
  15. 15.MaxRequestWorkers 400
  16. 16.MaxConnectionsPerChild 10000
  17. 17.ServerLimit 16
  18. 18.</IfModule>
  19. 19.`
  20. 20.MaxRequestWorkers = ServerLimit x ThreadsPerChild. With the values above: 16 x 25 = 400.
  21. 21.Calculate the safe maximum based on available memory:
  22. 22.```bash
  23. 23.ps -eo pid,rss,comm | grep apache2 | awk '{sum+=$2} END {print "Avg RSS:", sum/NR/1024, "MB"}'
  24. 24.`
  25. 25.If each Apache process uses 60MB and you have 8GB RAM reserved for Apache: 8192 / 60 = ~136 maximum workers.
  26. 26.Reduce KeepAlive timeout to free worker slots faster:
  27. 27.```apache
  28. 28.KeepAlive On
  29. 29.KeepAliveTimeout 5
  30. 30.MaxKeepAliveRequests 100
  31. 31.`
  32. 32.Lower KeepAliveTimeout from the default 15s to 5s so idle connections release worker slots sooner.
  33. 33.Enable mod_status monitoring to track worker usage in real time:
  34. 34.```apache
  35. 35.<Location "/server-status">
  36. 36.SetHandler server-status
  37. 37.Require ip 127.0.0.1 ::1 10.0.0.0/8
  38. 38.</Location>
  39. 39.ExtendedStatus On
  40. 40.`
  41. 41.Access at http://localhost/server-status to see real-time worker allocation.
  42. 42.Test and restart:
  43. 43.```bash
  44. 44.sudo apachectl configtest
  45. 45.sudo systemctl restart apache2
  46. 46.`

Prevention

  • Monitor worker utilization via server-status and alert when usage exceeds 80%
  • Use ab or wrk to load test and determine the optimal MaxRequestWorkers for your hardware
  • Consider switching from mpm_prefork to mpm_event with PHP-FPM for better concurrency
  • Implement request timeout limits: Timeout 60 and ProxyTimeout 120 to prevent slow requests from monopolizing workers
  • Use a reverse proxy (Nginx, HAProxy) in front of Apache to queue requests instead of dropping them
  • Add MaxConnectionsPerChild to prevent memory leaks from long-running processes