PHP-FPM Pool Configuration
Pool Configuration File
; /etc/php/8.1/fpm/pool.d/magento.conf
[magento]
; Pool name
; Used in Nginx fastcgi_pass
; Unix socket
listen = /var/run/php/php8.1-fpm-magento.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
; Or TCP
; listen = 127.0.0.1:9000
; Process management
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500
; Timeouts
request_terminate_timeout = 300s
request_slowlog_timeout = 5s
; Logging
slowlog = /var/log/php-fpm/magento-slow.log
php_admin_value[error_log] = /var/log/php-fpm/magento-error.log
php_admin_flag[log_errors] = on
; Memory
php_admin_value[memory_limit] = 756M
; OPcache
php_admin_value[opcache.enable] = 1
php_admin_value[opcache.memory_consumption] = 256M
php_admin_value[opcache.max_accelerated_files] = 20000
Pool Modes
; static: Fixed number of children
pm = static
pm.max_children = 50
; dynamic: Adjusts based on load
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
; ondemand: Creates children on demand
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
Socket vs TCP
; Unix socket (faster, same server)
listen = /var/run/php/php8.1-fpm-magento.sock
; TCP (network access, multiple servers)
listen = 127.0.0.1:9000
Key Takeaway
PHP-FPM pools define how PHP processes are managed. Use dynamic mode with appropriate max_children based on server memory. Unix sockets are faster than TCP for same-server communication.
Worker Management
Worker Calculation
# Formula: max_children = Available RAM / PHP per process
# Example:
# Server RAM: 8GB
# OS/Services: 2GB
# Available for PHP: 6GB
# PHP per process: 756MB
# Max children: 6GB / 756MB = ~8
# More conservative (with headroom):
# Max children = Available RAM / (PHP memory * 1.2)
# 6GB / (756MB * 1.2) = ~6
Worker Monitoring
# Check PHP-FPM status
sudo systemctl status php8.1-fpm
# Check pool status
curl http://localhost/fpm-status
# Check active processes
ps aux | grep php-fpm
# Count PHP-FPM processes
ps aux | grep -c 'php-fpm: pool'
Status Page Configuration
; Add to pool config
pm.status_path = /fpm-status
ping.path = /fpm-ping
ping.response = pong
; Enable in Nginx
location ~ ^/(fpm-status|fpm-ping)$ {
access_log off;
allow 127.0.0.1;
deny all;
fastcgi_pass unix:/var/run/php/php8.1-fpm-magento.sock;
include fastcgi_params;
}
Process Management Commands
# Restart PHP-FPM
sudo systemctl restart php8.1-fpm
# Reload configuration (graceful)
sudo systemctl reload php8.1-fpm
# Stop PHP-FPM
sudo systemctl stop php8.1-fpm
# Check configuration
sudo php-fpm8.1 -t
Worker Scaling
# Monitor and adjust based on traffic
# Peak hours: increase start_servers
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
# Off-peak: decrease to save memory
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 10
Key Takeaway
Calculate max_children based on available RAM and PHP memory limit. Use status page for monitoring. Adjust workers based on traffic patterns.
Performance Tuning
OPcache Configuration
; /etc/php/8.1/fpm/conf.d/10-opcache.ini
[opcache]
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.save_comments=1
opcache.fast_shutdown=1
Memory and Execution Limits
; /etc/php/8.1/fpm/php.ini
memory_limit = 756M
max_execution_time = 300
max_input_time = 300
post_max_size = 100M
upload_max_filesize = 100M
max_file_uploads = 20
Realpath Cache
; Increase realpath cache
realpath_cache_size = 4096K
realpath_cache_ttl = 600
``n
## Slow Log Analysis
```bash
# Enable slow log
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log
# Analyze slow log
awk '/^\[.*\]$/{ts=$0} /script_filename/{print ts, $0}' /var/log/php-fpm/slow.log | sort | uniq -c | sort -rn | head -20
OPcache Invalidation
# Clear OPcache
echo '<?php opcache_reset(); ?>' | sudo php
# Or restart PHP-FPM
sudo systemctl restart php8.1-fpm
Key Takeaway
Tune OPcache for compiled code caching, increase memory limits for Magento, configure realpath cache, and analyze slow logs for bottlenecks.
Monitoring and Debugging
Health Checks
#!/bin/bash
# php-fpm-health.sh
# Check PHP-FPM is running
if ! systemctl is-active php8.1-fpm > /dev/null; then
echo "PHP-FPM is not running!"
exit 1
fi
# Check socket exists
if [ ! -S /var/run/php/php8.1-fpm-magento.sock ]; then
echo "PHP-FPM socket not found!"
exit 1
fi
# Check status page
STATUS=$(curl -s http://localhost/fpm-status | head -1)
if [ -z "$STATUS" ]; then
echo "PHP-FPM status page not responding!"
exit 1
fi
echo "PHP-FPM is healthy"
Monitoring Metrics
# Key metrics to monitor
# 1. Process count
ps aux | grep -c 'php-fpm: pool'
# 2. Memory usage
ps aux | grep php-fpm | awk '{sum+=$6} END {print sum/1024 " MB"}'
# 3. Active connections
# Check FPM status page for 'active processes'
# 4. Slow requests
wc -l /var/log/php-fpm/slow.log
Debugging PHP-FPM
# Check error logs
tail -f /var/log/php-fpm/magento-error.log
# Check slow logs
tail -f /var/log/php-fpm/magento-slow.log
# Check PHP errors
tail -f /var/log/php/8.1/fpm/error.log
# Debug mode
php -d display_errors=1 -d error_reporting=E_ALL script.php
Common Issues and Fixes
# Issue: Too many workers
# Fix: Reduce pm.max_children or increase server RAM
# Issue: Slow requests
# Fix: Increase request_terminate_timeout, optimize code
# Issue: Socket not found
# Fix: Check listen configuration, restart PHP-FPM
# Issue: Memory exhaustion
# Fix: Reduce memory_limit or max_children
Key Takeaway
Monitor PHP-FPM health with status pages and scripts. Analyze slow logs for performance issues. Debug with error logs and PHP debug mode.
Quiz
1. How do you calculate PHP-FPM max_children?
2. What is the difference between Unix socket and TCP?
3. What does pm.status_path do?
4. Why use 'pm = dynamic' for Magento?
5. What does request_slowlog_timeout do?
Flashcards
Question
How to calculate max_children?
Click to reveal answer
Answer
Available RAM / PHP memory_limit per process (e.g., 6GB / 756MB = ~8)
Question
Unix socket vs TCP?
Click to reveal answer
Answer
Unix socket faster for same server, TCP for network access
Question
What is pm.status_path?
Click to reveal answer
Answer
Enables status page showing pool statistics for monitoring
Question
Why use dynamic PM mode?
Click to reveal answer
Answer
Adjusts workers based on traffic, balancing performance and memory
Question
What does request_slowlog_timeout do?
Click to reveal answer
Answer
Logs requests exceeding threshold for performance debugging
Question
How to reload PHP-FPM gracefully?
Click to reveal answer
Answer
sudo systemctl reload php8.1-fpm (no downtime)
Question
What is OPcache?
Click to reveal answer
Answer
Caches compiled PHP code in memory for faster execution
Question
How to clear OPcache?
Click to reveal answer
Answer
echo '<?php opcache_reset(); ?>' | sudo php
Revision Notes
Key Takeaways
- 1. Calculate max_children based on available RAM and PHP memory
- 2. Use Unix sockets for same-server, TCP for network
- 3. Enable status page for monitoring
- 4. Configure OPcache for compiled code caching
- 5. Analyze slow logs for performance issues
Interview Tips
- • Explain PHP-FPM pool configuration
- • Discuss worker calculation and scaling
- • Describe OPcache optimization
- • Explain monitoring and debugging approaches
Cheat Sheet
PHP-FPM Config
Pool Settings:
listen = /var/run/php/php8.1-fpm.sock
pm = dynamic
pm.max_children = RAM / memory_limit
Performance:
opcache.enable = 1
opcache.memory_consumption = 256M
opcache.max_accelerated_files = 20000
Monitoring:
pm.status_path = /fpm-status
slowlog = /var/log/php-fpm/slow.log
Commands:
sudo systemctl reload php8.1-fpm
sudo php-fpm8.1 -t
ps aux | grep php-fpm