In Apache's prefork MPM model, worker processes exist in two primary states:
# Sample output from apachectl status
Scoreboard Key:
"_" Waiting for Connection
"S" Starting up
"R" Reading Request
"W" Sending Reply
"K" Keepalive (read)
"D" DNS Lookup
"C" Closing connection
"L" Logging
"G" Gracefully finishing
"I" Idle cleanup
"." Open slot
The ratio between busy and idle workers reveals critical server performance insights:
- High Busy Workers (80%+ consistently): Indicates your server is struggling with request volume. Example scenario: When running WordPress with 50 concurrent users, seeing 90% busy workers suggests need for optimization.
- Low Idle Workers (Consistently below 10%): Shows inadequate capacity for traffic spikes. This appears when MaxClients is set too low for your traffic patterns.
Here's how to adjust worker settings in httpd.conf:
# Optimal configuration for a 4GB RAM server
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 10000
When analyzing worker states, consider these diagnostic commands:
# Real-time monitoring
watch -n 1 "curl -s http://localhost/server-status | grep -E 'Busy|Idle'"
# Historical analysis (requires mod_status enabled)
awk '/BusyWorkers/ {print $2}' /var/log/apache2/server-status.log
For high-traffic servers, implement these strategies:
- Worker Recycling: Prevent memory leaks by setting MaxConnectionsPerChild
- KeepAlive Optimization: Adjust KeepAliveTimeout based on your traffic pattern
- MPM Selection: Consider event MPM for better async handling
Example keepalive configuration:
KeepAlive On
KeepAliveTimeout 2
MaxKeepAliveRequests 100
Apache's worker model is fundamental to its performance. Each worker process handles incoming HTTP requests:
- Busy Workers: Currently processing requests (active threads)
- Idle Workers: Standing by for new connections (available threads)
# Sample output from mod_status
Scoreboard: _W___K____R____D______L_____I___C_____G......
Legend:
"_" Waiting for connection
"S" Starting up
"R" Reading request
"W" Sending reply
"K" Keepalive
"D" DNS lookup
"C" Closing connection
"L" Logging
"G" Gracefully finishing
"I" Idle cleanup
Monitoring the ratio between busy and idle workers reveals critical server health information:
- High busy/low idle: Indicates potential overload - requests queueing
- High idle count: Shows available capacity (but excessive idling may indicate resource waste)
A healthy Apache configuration typically maintains 20-30% idle workers during normal load.
Based on worker metrics, consider these adjustments in httpd.conf:
# Tune these directives based on worker metrics
StartServers 5
MinSpareServers 10
MaxSpareServers 20
ServerLimit 256
MaxRequestWorkers 150
MaxConnectionsPerChild 10000
Real-world tuning example for a high-traffic server:
# After observing 90% busy workers during peak:
StartServers 10 → 15
MinSpareServers 10 → 20
MaxRequestWorkers 150 → 200
Automate worker tracking with this bash snippet:
#!/bin/bash
while true; do
busy=$(curl -s http://localhost/server-status | grep -o 'W' | wc -l)
total=$(curl -s http://localhost/server-status | grep 'requests currently being processed' | awk '{print $1}')
echo "$(date) - Busy: $busy/$total ($(($busy*100/$total))%)"
sleep 5
done
When worker metrics indicate problems, check these areas:
- Slow application code - Profile PHP/Python/Ruby execution
- Database bottlenecks - Check query times
- External API delays - Monitor third-party service response times
- Insufficient RAM - Check for swapping (use free -m)
If worker metrics consistently show:
- >80% busy workers during 80% of peak hours
- Request queueing despite optimized settings
- Server resource limits reached
...it's time to consider load balancing across multiple Apache servers.
Enable detailed monitoring in httpd.conf:
ExtendedStatus On
<Location "/server-status">
SetHandler server-status
Require host localhost
</Location>
Then access via http://yourserver/server-status for real-time worker analysis.