Troubleshooting: Apache prefork server reached MaxRequestWorkers resource limit on Ubuntu 20.04 LTS
Resolve Apache prefork MaxRequestWorkers errors on Ubuntu 20.04. Learn to diagnose, calculate, and adjust server resource limits for optimal web server performance.
Resolve Apache prefork MaxRequestWorkers errors on Ubuntu 20.04. Learn to diagnose, calculate, and adjust server resource limits for optimal web server performance.
When your Apache web server on Ubuntu 20.04 LTS suddenly becomes unresponsive, serves "503 Service Unavailable" errors, or experiences significant slowdowns under load, one of the most common culprits for setups using the mpm_prefork module is hitting the MaxRequestWorkers resource limit. This guide provides a highly technical, step-by-step approach to diagnose and resolve this critical performance bottleneck.
Symptom & Error Signature
Users attempting to access your website will often encounter slow page loads, timeouts, or a "503 Service Unavailable" error page. From a server administrator's perspective, the first indicator will typically appear in your Apache error logs, usually located at /var/log/apache2/error.log.
You'll see repeated entries similar to these:
[Fri Aug 07 10:30:00.123456 2026] [mpm_prefork:error] [pid 12345] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
[Fri Aug 07 10:30:00.123678 2026] [mpm_prefork:error] [pid 12345] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
[Fri Aug 07 10:30:00.123901 2026] [mpm_prefork:error] [pid 12345] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
Simultaneously, inspecting system resources using tools like top, htop, or free -h might reveal high CPU usage (especially sy or us time) or, more commonly, high memory consumption by Apache processes, potentially leading to swap usage.
Root Cause Analysis
The mpm_prefork module (Multi-Processing Module – prefork) is designed for non-threaded web servers and environments where processes need to be isolated, such as those running older PHP versions via mod_php. It operates by creating a pool of server processes ready to handle incoming requests. Each Apache process handles one request at a time.
MaxRequestWorkersDefined: This directive sets the upper limit on the total number of simultaneous connections that Apache will handle. When this limit is reached, Apache stops accepting new connections until one of the existing processes finishes its current request. New incoming requests will be queued by the kernel or dropped entirely, leading to user-facing errors (e.g., 503 Service Unavailable).- Why it's reached:
- Insufficient Configuration: The default
MaxRequestWorkers(often 150 on Ubuntu) is too low for the actual traffic volume or the resource demands of the hosted applications. - Slow Application Code: Long-running PHP scripts, inefficient database queries, or external API calls that take an extended time to respond will hold Apache processes open, quickly exhausting the available workers.
- Resource Exhaustion: Each
preforkprocess consumes a certain amount of RAM. IfMaxRequestWorkersis set too high relative to available physical memory, the server will start swapping heavily, drastically slowing down performance and making processes unresponsive. This creates a death spiral where Apache processes become slower, holding onto workers longer, leading to more processes being needed, and further memory exhaustion. - DDoS/Traffic Spikes: Sudden, unexpected surges in legitimate traffic or malicious attacks can rapidly consume all available workers.
- KeepAlive Issues: While less common, overly aggressive
KeepAliveTimeoutsettings combined with a large number of concurrent slow clients can also tie up workers.
- Insufficient Configuration: The default
Understanding that mpm_prefork is memory-intensive (each worker is a full process with its own memory space) is crucial. Unlike mpm_worker or mpm_event which utilize threads within processes for concurrency and are much more memory-efficient, prefork scales by adding more processes.
Step-by-Step Resolution
Addressing the MaxRequestWorkers limit involves a combination of resource analysis, configuration adjustment, and potential application optimization.
1. Assess Current Server Resource Usage
Before making any changes, it's critical to understand your server's baseline performance and memory footprint.
# Check overall system memory and swap usage
free -h
# Monitor CPU, memory, and running processes interactively
htop
# Get average memory usage per Apache process (Resident Set Size - RSS)
# This command extracts the RSS (in KB) for all apache2 processes and calculates the average.
ps aux | grep apache2 | awk '{sum+=$6} END {if (NR>0) print sum/NR/1024 " MB"}'
Note down the average memory usage of an Apache process. This value is crucial for calculating an optimal
MaxRequestWorkerssetting without exhausting your system's RAM. Remember that this value can fluctuate based on the requests being served.
2. Locate and Backup Apache Configuration
The mpm_prefork configuration is typically found in /etc/apache2/mods-enabled/mpm_prefork.conf.
# Display the current prefork configuration
cat /etc/apache2/mods-enabled/mpm_prefork.conf
# Create a backup before editing
sudo cp /etc/apache2/mods-enabled/mpm_prefork.conf /etc/apache2/mods-enabled/mpm_prefork.conf.bak
A typical mpm_prefork.conf might look like this:
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
3. Calculate an Optimal MaxRequestWorkers Value
This is the most critical step. You need to balance the number of workers with your available RAM to prevent heavy swapping, which cripples performance.
- Determine Available RAM:
- From
free -h, identify your total physical RAM (e.g., 4GB, 8GB, 16GB). - Subtract RAM used by the OS, database (e.g., MySQL, PostgreSQL), PHP-FPM processes, and any other essential services. A safe buffer of 10-20% free RAM is recommended.
- Let's assume your server has 8GB RAM, and other services use 2GB, leaving 6GB for Apache.
- From
- Calculate Based on Average Process Size:
- Use the average Apache process size you obtained in Step 1 (e.g., if
ps auxshowed 20MB per process). MaxRequestWorkers = (Available RAM for Apache) / (Average Apache process size)- Example:
6000 MB / 20 MB/process = 300 MaxRequestWorkers
- Use the average Apache process size you obtained in Step 1 (e.g., if
Do NOT set
MaxRequestWorkershigher than what your RAM can comfortably support. Exceeding physical RAM will lead to excessive swapping, making your server extremely slow and potentially unresponsive. It is better to have fewer workers that are actively processing requests than many workers waiting for swapped memory.
4. Adjust mpm_prefork.conf
Edit the configuration file to reflect your calculated MaxRequestWorkers value. You may also need to adjust other related directives.
sudo nano /etc/apache2/mods-enabled/mpm_prefork.conf
Modify the MaxRequestWorkers line. Consider also adjusting ServerLimit if you set MaxRequestWorkers higher than the default ServerLimit (which often defaults to 256 or 150 on Ubuntu and limits MaxRequestWorkers). ServerLimit must be set equal to or greater than MaxRequestWorkers. It should be placed above MaxRequestWorkers.
<IfModule mpm_prefork_module>
StartServers 10
MinSpareServers 10
MaxSpareServers 20
ServerLimit 300 # Set this to the same or higher than MaxRequestWorkers
MaxRequestWorkers 300 # Your calculated value
MaxConnectionsPerChild 0 # 0 means processes never die, good for long-running apps
# Set to a positive value (e.g., 1000) if memory leaks are suspected.
</IfModule>
StartServers,MinSpareServers,MaxSpareServers: These settings control the number of idle server processes Apache keeps ready.
StartServers: The number of server processes to launch at startup.MinSpareServers: The minimum number of idle server processes to maintain.MaxSpareServers: The maximum number of idle server processes to maintain. Increasing these slightly can help with sudden traffic bursts by having more processes ready, but don't set them too high as they consume memory unnecessarily. Typically,MinSpareServersandMaxSpareServersshould be a small fraction ofMaxRequestWorkers.
5. Test Configuration and Restart Apache
Always test your Apache configuration for syntax errors before restarting.
sudo apache2ctl configtest
If the syntax is Syntax OK, restart Apache for the changes to take effect.
sudo systemctl restart apache2
After restarting, monitor your server's performance using
htop,free -h, and the Apache error logs (tail -f /var/log/apache2/error.log). Observe memory usage and if theAH00161errors reappear. If they do, theMaxRequestWorkersmight still be too low or your application requires further optimization.
6. Application and PHP Optimization (Crucial for Prefork)
Often, the MaxRequestWorkers limit is merely a symptom of inefficient application code.
- PHP-FPM: If you're using
mod_phpwithmpm_prefork, consider migrating toPHP-FPM(FastCGI Process Manager) withmpm_eventormpm_worker. PHP-FPM allows you to manage PHP processes separately, making Apache much lighter and more efficient by offloading PHP execution to dedicated pools. This is a highly recommended long-term solution for modern PHP applications.- Enable
mpm_eventormpm_worker:sudo a2dismod mpm_prefork sudo a2enmod mpm_event # or mpm_worker sudo a2enmod proxy_fcgi sudo systemctl restart apache2 - Configure PHP-FPM pools (e.g.,
/etc/php/8.1/fpm/pool.d/www.conf) and Apache'sproxy_fcgito connect to it.
- Enable
- Database Optimization: Optimize slow SQL queries, add missing indexes, and consider query caching.
- Caching: Implement application-level caching (e.g., Redis, Memcached) or reverse proxy caching (e.g., Nginx, Varnish) for frequently accessed static and dynamic content.
- Code Profiling: Use tools like Xdebug (for PHP) to identify bottlenecks in your application code.
7. Consider a Reverse Proxy (Nginx)
For high-traffic websites, placing Nginx as a reverse proxy in front of Apache is a common and effective strategy.
- Nginx can efficiently handle static file serving, SSL termination, and act as a highly performant load balancer, forwarding dynamic requests to Apache. This frees up Apache workers for only dynamic content.
- This also allows Nginx to buffer slow client connections, preventing them from tying up Apache processes.
# Example: Install Nginx
sudo apt update
sudo apt install nginx
sudo systemctl enable nginx
sudo systemctl start nginx
Then configure Nginx to proxy requests to Apache, typically running on localhost:8080.
8. Monitor and Iterate
Web server optimization is an ongoing process. Continuously monitor your server's resource usage, Apache logs, and application performance metrics. Adjust MaxRequestWorkers and other parameters incrementally based on observed behavior. Tools like Prometheus/Grafana or Zabbix can provide invaluable insights into long-term trends.