When configuring PHP-FPM for multi-site hosting, the memory calculation becomes significantly more complex than single-server scenarios. The critical parameter pm.max_children
must account for:
- Shared server resources across all sites
- Peak concurrent usage patterns
- Process memory variability (40-80MB in your case)
The basic formula Total RAM / Max Process Size
becomes dangerous in multi-tenant environments:
# Problematic calculation example
total_ram = 5120 # 5GB in MB
max_process = 80
naive_max_children = total_ram / max_process # Returns 64
This approach fails because it assumes only one application exists on the server. When multiplied by 30 sites, you correctly identified the potential memory explosion (76,800MB).
For your 30-site scenario with 5GB allocation, consider these approaches:
Method 1: Equal Share Partitioning
max_children_per_site = (total_ram * safety_factor) / (avg_process_size * site_count)
# Example with 0.8 safety factor:
(5120 * 0.8) / (40 * 30) = 3.41 → Round down to 3
Method 2: Tiered Allocation
Create priority groups in your PHP-FPM pool configurations:
; High-traffic site
[highpriority]
pm.max_children = 8
; Medium-traffic site
[mediumpriority]
pm.max_children = 4
; Low-traffic site
[lowpriority]
pm.max_children = 2
Implement real-time adjustment using these metrics:
- Track actual memory usage per pool:
ps -ylC php-fpm --sort:rss
- Monitor active processes:
pm.status_path = /status
- Set emergency limits:
emergency_children = max_children + 10%
Here's a safe baseline configuration for your environment:
[www]
user = www-data
group = www-data
listen = /run/php/php8.1-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 3
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.process_idle_timeout = 10s
pm.max_requests = 500
; Emergency overflow
php_admin_value[memory_limit] = 96M
php_admin_flag[emergency_restart_threshold] = 10
php_admin_flag[emergency_restart_interval] = 1m
Always validate with realistic traffic patterns:
# Sample load test command
siege -c 50 -t 2M -b http://yoursite.com/test.php
# Monitor memory during test
watch -n 1 "free -m && ps -eo pid,user,%mem,command | grep php-fpm"
When managing multiple PHP-FPM pools on a shared server, the traditional calculation method for pm.max_children
becomes insufficient. The standard formula:
pm.max_children = Available RAM / Largest Process Size
works well for single-application deployments but fails to account for resource contention in multi-tenant environments. Here's why this breaks down:
- Each FPM pool can independently spawn processes up to its
max_children
limit - Process memory usage varies between applications (40-80MB in your case)
- Simultaneous traffic spikes across sites create multiplicative memory demands
For your specific 8GB server hosting 30 sites with these characteristics:
Total available RAM: 5120MB (5GB dedicated to PHP-FPM)
Average process size: 40MB
Worst-case process size: 80MB
Number of websites: 30
The proper calculation requires two steps:
Step 1: Absolute System Limit
Absolute max = Total RAM / Largest Process
5120MB / 80MB = 64 processes (system-wide)
Step 2: Per-Pool Allocation
Per-pool max = Absolute max / Number of pools
64 / 30 ≈ 2 processes per pool
Instead of static allocations, consider implementing these advanced techniques:
; Dynamic scaling in php-fpm.conf
pm = dynamic
pm.max_children = 4 ; Absolute ceiling per pool
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 500
For a server running Nginx with multiple pools:
; /etc/php/8.2/fpm/pool.d/site1.conf
[site1]
user = site1
group = site1
listen = /run/php/site1.sock
pm = dynamic
pm.max_children = 4
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 500
php_admin_value[memory_limit] = 96M
Implement these monitoring solutions:
# Live process monitoring
sudo watch -n 2 'ps -ylC php-fpm --sort:rss | awk \'{print $8,$10}\''
# Memory tracking script
#!/bin/bash
TOTAL=$(free -m | awk \'/Mem:/ {print $2}\')
USED=$(ps -C php-fpm -o rss= | awk \'{sum+=$1} END {print sum/1024}\')
echo "PHP-FPM using ${USED}MB of ${TOTAL}MB total RAM"
- Implement OPCache to reduce process memory requirements
- Consider process recycling with
pm.max_requests
to prevent memory leaks - For high-traffic sites, isolate them to separate pools with higher limits
- Monitor actual peak usage patterns before finalizing limits