• 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 » Step-by-Step: Diagnosing Out of Memory (OOM) Killer terminating PHP-FPM pool workers on AWS Servers

Step-by-Step: Diagnosing Out of Memory (OOM) Killer terminating PHP-FPM pool workers on AWS Servers

Identifying the OOM Killer’s Handiwork

The first and most critical step in diagnosing OOM Killer events is to confirm that it’s indeed the culprit. Linux’s kernel employs the Out-Of-Memory (OOM) Killer as a last resort to reclaim memory when the system is critically low. This often manifests as unexpected process termination, and for PHP-FPM, it means your worker processes are being unceremoniously evicted.

The primary source of truth for OOM events is the system log. On most AWS EC2 instances running a modern Linux distribution (like Amazon Linux 2, Ubuntu, or CentOS/RHEL), these logs are typically found in /var/log/messages or /var/log/syslog. You can use grep to filter for OOM-related messages:

sudo grep -i "killed process" /var/log/messages
sudo grep -i "out of memory" /var/log/messages

Look for lines indicating a process was “killed process” or explicitly mentioning “Out of memory”. The output will usually include the process ID (PID), the process name (often php-fpm or a specific worker’s PID), and the amount of memory it was consuming. For example:

Oct 26 10:30:01 ip-172-31-10-5 kernel: [12345.678901] Out of memory: Kill process 9876 (php-fpm) score 1234 or sacrifice child
Oct 26 10:30:01 ip-172-31-10-5 kernel: [12345.679012] Killed process 9876 (php-fpm) total-vm:123456kB, anon-rss:65432kB, file-rss:1024kB

If you see these messages consistently, you’ve confirmed the OOM Killer is active. The next step is to understand *why* it’s being invoked.

Analyzing PHP-FPM Configuration for Memory Leaks

PHP-FPM’s memory consumption is heavily influenced by its process management configuration. The most common parameters to scrutinize are within your PHP-FPM pool configuration file, typically located at /etc/php-fpm.d/www.conf or a similar path depending on your distribution and PHP version.

Key directives to examine:

  • pm.max_children: The maximum number of child processes that will be spawned. If this limit is reached and requests are still coming in, requests will be queued or rejected.
  • pm.start_servers: The number of child processes to start when the FPM master process is started.
  • pm.min_spare_servers: The desired minimum number of idle supervisor processes.
  • pm.max_spare_servers: The desired maximum number of idle supervisor processes.
  • pm.process_idle_timeout: The number of seconds after which an idle process will be killed.
  • pm.max_requests: The number of requests each child process will execute before respawning. Setting this to a finite number helps mitigate memory leaks in long-running scripts.

A common cause of OOM is setting pm.max_children too high for the available RAM, or having a memory leak in your PHP application that causes individual workers to consume excessive memory over time. If pm.max_requests is set to 0 (or not set), a worker process will run indefinitely, making it a prime candidate for accumulating memory if there’s a leak.

Consider the total memory available on your EC2 instance. If you have a t3.medium instance with 4GB of RAM, and you set pm.max_children to 100, each worker process will have, on average, only 40MB of RAM available (before accounting for the OS, web server, database, etc.). This is often insufficient for modern PHP applications.

A good starting point for pm.max_children is to calculate the available RAM per worker. Let’s say your server has 4GB (4096MB) of RAM and you want to reserve 1GB for the OS and other services. That leaves 3GB (3072MB) for PHP-FPM. If your average PHP-FPM worker consumes 100MB of RAM, you could theoretically support 30 children (3072MB / 100MB). However, it’s safer to be conservative and start lower, perhaps 15-20, and monitor.

; Example /etc/php-fpm.d/www.conf
[www]
user = www-data
group = www-data
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 20       ; Start with a conservative number
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.process_idle_timeout = 10s
pm.max_requests = 500      ; Crucial for mitigating leaks

After adjusting these settings, restart PHP-FPM:

sudo systemctl restart php7.4-fpm

Monitor your logs again to see if the OOM events subside.

Profiling PHP Applications for Memory Leaks

If adjusting PHP-FPM configuration doesn’t resolve the issue, the problem likely lies within your PHP application code itself. Memory leaks in PHP can occur due to various reasons, including:

  • Holding large arrays or objects in memory for extended periods.
  • Circular references that prevent garbage collection (though PHP’s garbage collector is generally good at handling these).
  • Inclusion of large files or data structures that are not properly unset.
  • Third-party libraries with their own memory management issues.

To identify these leaks, you need profiling tools. The most popular and effective tool for PHP is Xdebug, often used in conjunction with a profiler like KCacheGrind (or its web-based alternative, Webgrind). Alternatively, you can use dedicated memory profiling tools.

1. Enabling Xdebug Profiling:

Ensure Xdebug is installed and configured in your php.ini. You’ll want to enable profiling and specify an output directory. A common location for Xdebug logs is /var/log/xdebug/. Make sure the web server user (e.g., www-data) has write permissions to this directory.

; In your php.ini or a dedicated xdebug.ini file
xdebug.mode = profile
xdebug.output_dir = "/var/log/xdebug"
xdebug.profiler_enable_trigger = 1 ; Enable profiling via a trigger (e.g., cookie or GET/POST parameter)
xdebug.profiler_trigger_value = "XDEBUG_PROFILE" ; The value to trigger profiling
xdebug.collect_assignments = 1
xdebug.collect_return_values = 1

Restart your web server (e.g., Nginx/Apache) and PHP-FPM for these changes to take effect.

2. Triggering Profiling:

When you encounter a request that seems to be consuming excessive memory or is likely to be killed by OOM, trigger Xdebug profiling. This can be done by adding a GET or POST parameter to your request, or by setting a cookie. For example, if you’re testing a specific page /api/process_data:

GET /api/process_data?XDEBUG_PROFILE=1 HTTP/1.1

This will generate a cachegrind.out.PID file in your xdebug.output_dir. The file contains detailed information about function calls, execution time, and importantly for memory, the number of calls and the self-cost (which can indirectly indicate memory usage if functions allocate memory).

3. Analyzing Profiler Output:

Use KCacheGrind or Webgrind to open the generated cachegrind file. Look for functions that are called an unusually high number of times, or functions that have a high “Self Cost” (which can be a proxy for memory allocation if the function’s primary job is to allocate memory). Pay close attention to functions that are called repeatedly within loops or recursive calls.

4. Using Memory Profilers (e.g., Blackfire.io, Tideways):

For more direct memory analysis, dedicated tools like Blackfire.io or Tideways are invaluable. These tools provide detailed breakdowns of memory usage per function, object creation, and memory leaks. They often offer a more intuitive interface for identifying memory hogs.

After installing the Blackfire/Tideways agent and PHP extension, you can profile requests and view detailed reports in their web UI. Look for functions that allocate significant amounts of memory, or for memory usage that grows over time during a single request’s execution.

System-Level Memory Monitoring and Tuning

Beyond PHP-FPM and application code, the underlying operating system and its configuration play a role. On AWS, you have several tools at your disposal.

1. CloudWatch Metrics:

AWS CloudWatch provides crucial metrics for your EC2 instances. Ensure you are collecting:

  • CPUUtilization: High CPU can sometimes correlate with processes struggling to manage memory.
  • MemoryUtilization (if using the CloudWatch agent): This is the most direct metric for overall system memory usage.
  • DiskReadOps and DiskWriteOps: Excessive swapping to disk can indicate memory pressure.

Set up CloudWatch Alarms for MemoryUtilization (if available) or for CPUUtilization and DiskI/O to proactively alert you to potential memory issues before the OOM Killer is invoked.

2. Swappiness:

Linux uses swap space (a partition or file on disk) when physical RAM is exhausted. High swap usage is a strong indicator of memory pressure. The swappiness kernel parameter controls how aggressively the kernel swaps memory pages. A value of 0 means the kernel will avoid swapping as much as possible, while 100 means it will swap aggressively. For servers running memory-sensitive applications like PHP-FPM, a lower swappiness value (e.g., 10 or 20) is often recommended to prioritize keeping application data in RAM.

Check current swappiness:

cat /proc/sys/vm/swappiness

To temporarily change it:

sudo sysctl vm.swappiness=10

To make it permanent, edit /etc/sysctl.conf or a file in /etc/sysctl.d/:

# /etc/sysctl.conf
vm.swappiness = 10

Then apply the changes:

sudo sysctl -p

3. Monitoring with top, htop, and free:

While troubleshooting, regularly use command-line tools to monitor memory usage. htop is a more user-friendly alternative to top.

htop

Look for processes consuming a large percentage of memory (%MEM column) or resident set size (RES). The free -h command provides a quick overview of total, used, free, shared, buff/cache, and available memory, as well as swap usage.

free -h

Pay attention to the “available” memory, which is a better indicator of how much memory is actually free for new applications. If “available” memory is consistently very low, and swap is being used heavily, you are approaching critical memory limits.

AWS Instance Sizing and Scaling Strategies

Sometimes, the issue isn’t a leak but simply that your workload exceeds the capacity of your current EC2 instance. This is where proper instance sizing and scaling come into play.

1. Right-Sizing Instances:

Analyze your CloudWatch metrics and historical performance data. If your instance is consistently maxing out its CPU or memory, it might be time to move to a larger instance type. Consider instances optimized for compute (e.g., `c` series) or memory (e.g., `r` series) depending on your application’s bottleneck.

2. Auto Scaling Groups:

For web applications, leveraging AWS Auto Scaling Groups is a robust solution. Configure your EC2 instances to launch and terminate based on metrics like CPU utilization, network traffic, or custom metrics (e.g., request queue length). This ensures you have enough capacity during peak loads and scale down during off-peak times to save costs.

When using Auto Scaling Groups with PHP-FPM, ensure your AMIs are pre-configured with PHP-FPM and your application code. The scaling policies should be tuned to react quickly enough to prevent memory exhaustion but not so aggressively that they cause constant churn.

3. Load Balancers:

Use Elastic Load Balancers (ELB) to distribute traffic across multiple EC2 instances. This prevents any single instance from becoming overwhelmed and allows for seamless scaling.

Conclusion

Diagnosing OOM Killer events terminating PHP-FPM workers on AWS requires a systematic approach. Start by confirming the OOM Killer’s involvement via system logs. Then, meticulously review your PHP-FPM configuration, paying close attention to process management directives and the pm.max_requests setting. If configuration adjustments aren’t enough, dive deep into your PHP application code using profiling tools like Xdebug or Blackfire to pinpoint memory leaks. Finally, ensure your AWS infrastructure is appropriately sized and configured, leveraging CloudWatch for monitoring and Auto Scaling for dynamic capacity management. By combining these strategies, you can effectively combat the OOM Killer and maintain a stable, performant PHP environment.

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

  • Leveraging PHP 8.3 JIT and OPcache for Extreme Laravel Performance: A Deep Dive into Micro-Optimizations and Benchmarking
  • Orchestrating Zero-Downtime Deployments with Laravel, Docker Swarm, and AWS ECS: A Deep Dive into GitOps Workflows
  • Leveraging Docker Swarm for High-Availability WordPress Headless Deployments with Automated Rollbacks and Performance Monitoring
  • Real-time Observability for Laravel Applications on Kubernetes: Mastering Prometheus, Grafana, and Loki
  • Leveraging Laravel Forge & Envoyer for Zero-Downtime Deployments with Dockerized PHP 9 Microservices on AWS EKS

Categories

  • apache (1)
  • AWS (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (664)
  • Desktop Applications (14)
  • DevOps (49)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (45)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (873)
  • Performance & Security Optimization (7)
  • PHP (163)
  • PHP Development (49)
  • Plugins & Themes (244)
  • Programming Languages (10)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (650)
  • SEO & Growth (492)
  • Server (118)
  • Softwares (1)
  • Ubuntu (9)
  • Uncategorized (319)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (92)
  • WordPress Plugin Development (728)
  • WordPress Theme Development (357)

Recent Posts

  • Leveraging PHP 8.3 JIT and OPcache for Extreme Laravel Performance: A Deep Dive into Micro-Optimizations and Benchmarking
  • Orchestrating Zero-Downtime Deployments with Laravel, Docker Swarm, and AWS ECS: A Deep Dive into GitOps Workflows
  • Leveraging Docker Swarm for High-Availability WordPress Headless Deployments with Automated Rollbacks and Performance Monitoring

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (728)
  • Debugging & Troubleshooting (664)
  • Security & Compliance (650)
  • SEO & Growth (492)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala