When running WordPress on an EC2 micro instance with limited RAM, you'll often encounter Apache's prefork MPM spawning hundreds of processes that eventually crash your server. These processes frequently get stuck in uninterruptible sleep (D state), indicating I/O wait issues. Let's examine a proper configuration for memory-constrained environments.
The default Apache configuration assumes significant available memory. For a 1GB RAM system running both Apache and MySQL, we need aggressive tuning:
# Recommended settings for 1GB RAM system
StartServers 2
MinSpareServers 2
MaxSpareServers 5
MaxRequestWorkers 30
MaxConnectionsPerChild 1000
KeepAlive On
KeepAliveTimeout 2
MaxKeepAliveRequests 100
WordPress's dynamic nature exacerbates process growth. Implement these adjustments:
# In wp-config.php
define('WP_MEMORY_LIMIT', '64M');
define('WP_MAX_MEMORY_LIMIT', '128M');
# In .htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
When processes get stuck in D state, investigate with:
# Check for disk I/O bottlenecks
iotop -oPa
vmstat 1 10
# Identify blocking processes
cat /proc/[pid]/stack
strace -p [pid]
Combine these settings with PHP-FPM tuning for better resource management:
# In php-fpm.conf
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 4
pm.max_requests = 500
# In httpd.conf
Timeout 60
HostnameLookups Off
EnableSendfile Off
For extremely resource-constrained systems, consider:
- Switching to lighttpd or nginx with PHP-FPM
- Implementing a reverse proxy cache like Varnish
- Using a static site generator for low-traffic blogs
When monitoring top
or htop
, seeing dozens of Apache processes stuck in D-state (uninterruptible sleep) typically indicates blocked I/O operations. On WordPress setups, this often traces back to:
# Common culprits in error logs
tail -f /var/log/httpd/error_log | grep -i "D state"
# Sample output showing blocked processes
[proxy_fcgi:error] (70007)The timeout specified has expired: [client x.x.x.x] AH01075: Error dispatching request to : (interrupted syscall)
Your EC2 micro instance needs aggressive process limits. The commented directives in your config should be activated with these values:
StartServers 2
MinSpareServers 2
MaxSpareServers 5
MaxRequestWorkers 20 # Lower than your RAM allows
ServerLimit 20
MaxConnectionsPerChild 500 # Kills processes after 500 requests
Timeout 30 # Default 300 is too high
KeepAliveTimeout 2
Add these to wp-config.php to reduce PHP process overhead:
define('WP_MEMORY_LIMIT', '64M');
define('WP_MAX_MEMORY_LIMIT', '128M');
define('WP_CACHE', true); // Enable caching
Use this bash snippet to identify stuck processes:
while true; do
date;
ps auxf | grep '[h]ttpd' | wc -l;
ps auxf | grep '[D] state' | awk '{print $2}' | xargs -r lsof -p;
sleep 5;
done
Consider switching to event MPM if your Apache version supports it:
# In httpd.conf
LoadModule mpm_event_module modules/mod_mpm_event.so
StartServers 2
MinSpareThreads 20
MaxSpareThreads 40
ThreadsPerChild 25
MaxRequestWorkers 100
MaxConnectionsPerChild 1000