• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Resolving Out of Memory (OOM) Killer terminating PHP-FPM pool workers Under Peak Event Traffic on OVH

Resolving Out of Memory (OOM) Killer terminating PHP-FPM pool workers Under Peak Event Traffic on OVH

Diagnosing the OOM Killer’s Intervention

When PHP-FPM pool workers are being terminated by the Linux Out-of-Memory (OOM) Killer during peak traffic events, it’s a critical indicator of resource exhaustion. This isn’t a graceful shutdown; it’s the kernel forcibly reclaiming memory to prevent a system-wide crash. The immediate goal is to identify which processes are consuming excessive memory and why. On OVH infrastructure, this often involves a combination of system-level monitoring and PHP-FPM configuration tuning.

The first step is to confirm the OOM Killer’s involvement. System logs are your primary source. Look for messages from dmesg or /var/log/syslog (or /var/log/messages depending on your distribution) that explicitly mention “Out of memory: Kill process” or similar phrasing, along with the process ID (PID) and the process name. Often, the PID will correspond to a PHP-FPM worker process.

System-Level Memory Analysis

Before diving deep into PHP-FPM, let’s establish a baseline of system memory usage. Tools like top, htop, and vmstat are invaluable. During a period of high traffic (or immediately after an OOM event), run these commands to get a snapshot of memory consumption.

Using top and htop

htop is generally preferred for its interactive and color-coded output. Sort by memory usage (press ‘M’ in htop) to quickly identify the top memory consumers. Pay close attention to the RES (Resident Set Size) and %MEM columns.

# On a system experiencing high load or after an OOM event
htop

Look for multiple php-fpm processes consuming a significant portion of the available RAM. If a single php-fpm worker is consistently high, it points to an issue within that specific worker’s execution. If the aggregate memory of all php-fpm workers is high, it suggests either too many workers or individual workers consuming too much memory.

Using vmstat for Historical Trends

vmstat can provide a more historical view, especially when run with an interval. This helps correlate memory spikes with specific events or traffic patterns.

# Monitor memory, swap, and process activity every 5 seconds
vmstat 5

Key columns to watch:

  • swpd: Amount of virtual memory used. A high or increasing value indicates swap usage, which is a strong sign of memory pressure.
  • free: Amount of idle memory. A consistently low value is problematic.
  • buff and cache: Memory used for buffers and cache. While these are generally good, a system under extreme pressure might reclaim them.
  • si and so: Swap-in and swap-out. Non-zero values here indicate active swapping, a critical performance bottleneck and precursor to OOM.
  • procs r and procs b: Number of runnable processes and processes in uninterruptible sleep (often I/O bound or waiting). High values can indicate system overload.
  • memory si and memory sr: Swap-in and swap-out rates.

PHP-FPM Configuration Tuning

The PHP-FPM configuration file (typically /etc/php/[version]/fpm/php-fpm.ini and pool configurations in /etc/php/[version]/fpm/pool.d/) is the primary lever for controlling worker behavior and memory limits.

Understanding PHP-FPM Process Management Modes

PHP-FPM offers several process management strategies. The choice significantly impacts memory usage and stability.

Static vs. Dynamic vs.ondemand

1. Static: A fixed number of child processes are spawned when the master process starts. This offers predictable performance but can be memory-inefficient if idle workers consume too much memory. It’s often the best choice for predictable, high-load scenarios if memory is sufficient.

2. Dynamic: The number of child processes varies between pm.min_spare_servers and pm.max_children based on demand. This is a good balance but can lead to spikes in memory usage as new processes are spawned.

3. ondemand: Processes are spawned only when a request comes in and are killed after a period of inactivity. This is the most memory-efficient but can introduce latency for the first request after a period of idleness.

Key `pm` Directives and Their Impact

These directives are usually found in your pool configuration file (e.g., /etc/php/[version]/fpm/pool.d/www.conf).

`pm.max_children`

This is the most critical directive. It defines the absolute maximum number of child processes that can be spawned. Setting this too high is a direct cause of OOM. Setting it too low starves your application of concurrency.

Calculation: A rough estimate for max_children can be derived from your server’s total RAM and the average memory footprint of a single PHP-FPM worker process.
Total RAM (MB) / Average Worker Memory (MB) = Max Children (approx.)
Remember to leave ample memory for the OS, web server (Nginx/Apache), database, and other services. A conservative approach is often best.

Example configuration snippet:

; pm = static
; pm.max_children = 50 ; Example: If each worker uses ~100MB and you have 4GB RAM, 4096MB / 100MB = ~40. Reserve ~1GB for OS/other services.

; OR for dynamic
pm = dynamic
pm.max_children = 100 ; Higher limit for dynamic, but still needs careful consideration
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500 ; Number of requests each child process should execute before respawning. Helps prevent memory leaks.

`pm.process_idle_timeout`

Relevant for dynamic and ondemand modes. This is the number of seconds after which an idle process will be killed. Lowering this can free up memory faster but might increase CPU usage due to frequent process spawning/killing.

; For pm = ondemand
pm.process_idle_timeout = 10s ; Kill idle processes after 10 seconds

; For pm = dynamic
; pm.max_requests = 500 ; Also helps manage memory by respawning workers periodically

`pm.max_requests`

This directive sets the number of child processes that will be killed and restarted after they have executed a given number of requests. Setting this to a reasonable value (e.g., 500-1000) is crucial for mitigating memory leaks in long-running PHP applications. If a script has a memory leak, it will eventually consume all available memory for that worker. `pm.max_requests` ensures that worker is recycled before it becomes a problem.

PHP Memory Limit (`memory_limit`)

While memory_limit in php.ini (or set via ini_set() in your scripts) limits the memory a *single PHP script execution* can consume, it’s distinct from the PHP-FPM worker’s total memory footprint. A worker process also includes the PHP interpreter itself, extensions, and overhead. However, if individual scripts are hitting the memory_limit frequently, it can contribute to the overall memory pressure on the worker.

If you see specific scripts consistently failing with “Allowed memory size of X bytes exhausted,” you need to address those scripts first. However, if the OOM killer is hitting the *worker process itself*, it’s usually a configuration issue with PHP-FPM’s process management or insufficient system RAM.

Profiling PHP Code for Memory Leaks

If tuning PHP-FPM settings doesn’t fully resolve the issue, or if you suspect specific scripts are the culprits, memory profiling is necessary. This is where you identify inefficient code, large data structures, or actual memory leaks within your PHP application.

Using Xdebug’s Profiler

Xdebug, when configured for profiling, can generate detailed call graphs and memory usage statistics. You’ll need to enable the profiler in your php.ini or via XDEBUG_CONFIG environment variable.

; In php.ini or a conf.d file
xdebug.mode = profile
xdebug.output_dir = /tmp/xdebug_profiling
xdebug.profiler_enable_trigger = 1 ; Enable profiling via trigger (e.g., GET/POST parameter)
xdebug.profiler_trigger_value = "PROFILE" ; The value to trigger profiling

Then, access a specific URL with the trigger:

https://your-domain.com/your-script.php?XDEBUG_PROFILE=PROFILE

This will generate files in /tmp/xdebug_profiling. Tools like KCacheGrind (for Linux/macOS) or Webgrind (web-based) can visualize these profiling results, showing function calls and their memory consumption.

Using Blackfire.io

Blackfire.io is a powerful, production-ready profiling tool. It provides deep insights into CPU, memory, I/O, and network usage with minimal overhead. It’s often easier to set up and interpret than Xdebug for complex applications.

Installation typically involves installing the Blackfire agent and PHP extension. Once configured, you can trigger profiles via a browser extension or command-line tool.

# Example command-line profiling
blackfire run --php /usr/bin/php your_script.php

# Or via web request using the browser extension

Blackfire’s web UI provides detailed breakdowns of memory usage per function, allowing you to pinpoint memory hogs.

System-Level Memory Tuning and Monitoring

Beyond PHP-FPM, ensure your server is adequately provisioned and configured.

Swappiness

The swappiness kernel parameter controls how aggressively the system swaps memory pages to disk. A high value (e.g., 60, the default on many systems) means the kernel will swap more readily. For servers running memory-intensive applications like PHP-FPM, reducing swappiness can prevent the system from entering a swap-heavy state that precedes OOM events.

# Check current swappiness
cat /proc/sys/vm/swappiness

# Temporarily set swappiness to 10 (less aggressive swapping)
sudo sysctl vm.swappiness=10

# Make it permanent by editing /etc/sysctl.conf
# Add or modify the line:
# vm.swappiness = 10

A value of 10 is often a good starting point for production servers. Values of 0 or 1 can be too aggressive and might lead to processes being killed prematurely if memory is tight, but for PHP-FPM, a lower value is generally beneficial.

Monitoring Tools

Implement robust monitoring. Tools like Prometheus with Node Exporter, Zabbix, or Datadog can track memory usage trends over time, alert you to approaching thresholds, and help correlate OOM events with traffic spikes or specific application deployments.

Key metrics to monitor:

  • Total System Memory Usage
  • Swap Usage
  • PHP-FPM Worker Count (active, idle)
  • Average/Max Memory per PHP-FPM Worker
  • Load Average
  • I/O Wait

OVH Specific Considerations

OVH offers various server types (Dedicated, VPS, Public Cloud). The specific resource allocation and network configuration can influence memory behavior. Ensure you understand the RAM allocated to your instance. For Public Cloud instances, consider the performance profiles and disk I/O, which can indirectly affect application performance and memory usage.

If you are on a VPS or a dedicated server with limited RAM, the `pm.max_children` directive becomes extremely sensitive. You might need to run PHP-FPM in `static` mode with a carefully calculated `max_children` value that leaves significant headroom for the OS and other services. For example, on a 4GB RAM server, if PHP-FPM workers average 80MB each, and you need 1GB for the OS/Nginx/DB, you have 3GB (3072MB) for PHP-FPM. 3072MB / 80MB ≈ 38 children. So, `pm.max_children = 35` would be a safer starting point.

Step-by-Step Resolution Workflow

  • 1. Confirm OOM Killer: Check dmesg and system logs for “Out of memory: Kill process”. Note the PID and process name.
  • 2. Baseline System Memory: Use htop (sorted by memory) and vmstat 5 during peak times to understand overall memory pressure and swap usage.
  • 3. Analyze PHP-FPM Configuration: Review php-fpm.conf and pool configurations (e.g., www.conf).
  • 4. Adjust `pm.max_children`: This is the most common culprit. Calculate a safe value based on available RAM and average worker memory footprint. Start conservatively.
  • 5. Tune `pm.max_requests`: Set a reasonable value (e.g., 500-1000) to mitigate memory leaks.
  • 6. Consider `pm` Mode: If memory is extremely constrained, `ondemand` might be necessary, but be aware of potential latency. For stable high load, `static` with a tuned `max_children` is often best.
  • 7. Review `memory_limit`: Ensure individual PHP scripts aren’t excessively consuming memory, though this is less likely to trigger the *system* OOM killer directly unless it contributes to worker bloat.
  • 8. Profile Code: If tuning doesn’t help, use Xdebug or Blackfire to identify and fix memory leaks in your PHP application.
  • 9. Tune System Settings: Lower `swappiness` (e.g., to 10) to reduce aggressive swapping.
  • 10. Implement Monitoring: Set up alerts for memory usage, swap, and PHP-FPM worker counts.
  • 11. Scale Resources: If all else fails and your application genuinely requires more memory, consider upgrading your OVH instance or optimizing database/caching layers.

By systematically applying these steps, you can diagnose and resolve the OOM Killer’s termination of PHP-FPM workers, ensuring stability even under peak event traffic.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Top 100 Developer Tooling and Productivity SaaS Ideas to Launch in 2026 to Boost Organic Search Growth by 200%
  • Top 100 Developer-Centric Code Snippet Managers and Customization Plugins to Double User Engagement and Session Duration
  • Top 5 API Monetization Frameworks and Gateway Strategies for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Premium Newsletter and Subscription Business Models for Devs for High-Traffic Technical Portals

Categories

  • apache (1)
  • Business & Monetization (386)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (514)
  • DevOps (7)
  • DevOps & Cloud Scaling (929)
  • Django (1)
  • Migration & Architecture (108)
  • MySQL (1)
  • Performance & Optimization (665)
  • PHP (5)
  • Plugins & Themes (147)
  • Security & Compliance (527)
  • SEO & Growth (457)
  • Server (23)
  • Ubuntu (9)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (112)

Recent Posts

  • Top 100 Developer Tooling and Productivity SaaS Ideas to Launch in 2026 to Boost Organic Search Growth by 200%
  • Top 100 Developer-Centric Code Snippet Managers and Customization Plugins to Double User Engagement and Session Duration
  • Top 5 API Monetization Frameworks and Gateway Strategies for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Premium Newsletter and Subscription Business Models for Devs for High-Traffic Technical Portals
  • Top 100 SEO and Schema Markup Plugins for Headless Decoupled Sites for Independent Web Developers and Indie Hackers

Top Categories

  • DevOps & Cloud Scaling (929)
  • Performance & Optimization (665)
  • Security & Compliance (527)
  • Debugging & Troubleshooting (514)
  • SEO & Growth (457)
  • Business & Monetization (386)

Our Products

  • School Management & Student Administration System
  • Integrated Hospital & Clinic Management System
  • Real Estate Directory & Agent Portal
  • Restaurant POS & Table Booking System
  • Retail Inventory POS & Billing System
  • Pharmacy Inventory & Clinic Billing System

Our Services

  • Vibe Engineering & AI Code Auditing Services
  • Prompt Engineering & "Vibe Coding" Workflow Consulting
  • AI-Augmented "Vibe Coding" & Rapid MVP Development
  • Figma to Shopify Liquid Theme Customization
  • Figma to WooCommerce Frontend Development
  • Figma to Magento 2 Theme Development

Copyright © 2026 · Vinay Vengala