How to fix 'Too many open files' on Linux for PHP‑FPM during traffic spikes

By · Published on · 7 min read

Painel com vários monitores e interfaces digitais iluminadas em uma sala de controle
Transmite monitoramento e operações durante picos de tráfego Photo: Keysi Estrada / Pexels

How to fix 'Too many open files' on Linux for PHP‑FPM during traffic spikes: understand what exhausts file descriptors (FDs), how to diagnose it in production, and which adjustments to apply at each layer (systemd, kernel, FPM, Nginx). Below are practical steps to stabilize systems without promising miracles.

Real symptoms and when this error shows up

It happens at traffic peaks, when PHP‑FPM accepts new connections while holding FDs open: sockets, log files, temp files and upstream connections. Symptoms include 502/504 from Nginx, intermittent API failures and 'Too many open files' messages in FPM and web server logs.

Do not confuse this with ephemeral port exhaustion. Here the issue is the file descriptor ceiling for the process, the service or the kernel.

  • 502/504 and brief outages under load.
  • ‘Too many open files’ entries in PHP‑FPM logs.
  • Increased latency and request queues at the web server.
  • Database and cache connections failing due to insufficient FDs.

Immediate diagnosis in production (stay calm)

Do three checks: 1) confirm the error in logs; 2) inspect the effective FD limit of the FPM master; 3) count open FDs to see the gap. This tells you which layer needs adjustment. If you already export metrics, correlate FPM queueing with FD usage — see how to expose PHP‑FPM metrics.

# 1) Confirme no log do FPM
sudo grep -i "too many open files" /var/log/php*-fpm*.log || true

# 2) Descubra o PID do master do PHP-FPM
pgrep -x "php-fpm" || pgrep -x "php-fpm8.2" || pgrep -x "php-fpm7.4"
PID=<<coloque_o_pid_aqui>>

# Limites efetivos do processo (procfs)
cat /proc/$PID/limits | grep -i "open files"

# Também veja o LimitNOFILE do unit systemd correspondente
systemctl show php-fpm --property=LimitNOFILE 2>/dev/null || \
  systemctl show php8.2-fpm --property=LimitNOFILE 2>/dev/null

# 3) Quantos FDs o master mantém abertos agora?
lsof -p $PID | wc -l

# Tipos mais comuns de FDs (visão rápida)
lsof -p $PID | awk '{print $5}' | sort | uniq -c | sort -nr | head -n 10

Where the limit comes from: layers that control FDs

The FD ceiling is the combination of kernel, service manager and app. Changing only the shell ulimit does not affect services managed by systemd. Understand the stack before making changes.

Layer Where to change Main parameter How to check
Kernel (global) /etc/sysctl.d/*.conf fs.file-max sysctl fs.file-max
Systemd (service) unit override LimitNOFILE systemctl show <unit> --property=LimitNOFILE
PHP‑FPM (pool) www.conf (or pool file) rlimit_files /proc/$PID/limits (Open files)
Nginx (worker) nginx.conf worker_rlimit_nofile nginx -T | grep rlimit
Shell/PAM (login) /etc/security/limits*.conf nofile ulimit -n (in interactive session)
Containers (Docker) compose.yaml / run ulimits: nofile docker inspect ... | jq '.[0].HostConfig.Ulimits'

Quick fix focused on the service (systemd + FPM)

Increase LimitNOFILE in the PHP‑FPM unit and optionally set rlimit_files in the pool. This requires a service restart because limits are applied when the process is created. To reduce user impact, consider a traffic shift using a blue‑green deploy pattern before restarting.

  • Use a value with headroom for the expected peak.
  • Check logs after restart to confirm.
  • Do not exceed the kernel capacity (fs.file-max).
# 1) Override no systemd
sudo systemctl edit php-fpm || sudo systemctl edit php8.2-fpm
# Adicione no editor que abrir:
# [Service]
# LimitNOFILE=131072

sudo systemctl daemon-reload
sudo systemctl restart php-fpm || sudo systemctl restart php8.2-fpm

# 2) (Opcional) rlimit_files no pool do FPM
# Em /etc/php/*/fpm/pool.d/www.conf ou similar:
# rlimit_files = 131072
# Depois, reinicie o PHP-FPM novamente.

# Valide
systemctl show php-fpm --property=LimitNOFILE 2>/dev/null || \
  systemctl show php8.2-fpm --property=LimitNOFILE 2>/dev/null
cat /proc/$(pgrep -x php-fpm | head -n1)/limits | grep -i "open files"

Persistent adjustments and safe scaling

Ensure the kernel and the service can support the new ceiling. Adjust fs.file-max and review FPM pool parameters to avoid uncontrolled growth. Do not raise limits without monitoring CPU, memory and I/O, otherwise you may simply move the bottleneck elsewhere.

  • Kernel: increase fs.file-max persistently.
  • FPM: review pm.max_children and pm.process_idle_timeout.
  • Logs: proper rotation avoids too many log FDs being held open.
# Kernel: persistir um teto global mais alto
echo 'fs.file-max = 1000000' | sudo tee /etc/sysctl.d/99-fd.conf
sudo sysctl --system

# PHP-FPM (pool): além de rlimit_files, confira a capacidade de workers
# Ex.: pm = dynamic; pm.max_children = <valor_compatível_com_recursos>
# Consulte a documentação oficial do PHP-FPM para detalhes dos parâmetros.

Nginx, connections and interplay with containers (Docker)

If Nginx proxies to FPM, its workers also need a higher ceiling. In containers, define ulimits per service. Note that container limits do not inherit from the host by default. If you're evaluating reverse proxies, see criteria in Traefik vs Nginx.

  • Nginx: adjust worker_rlimit_nofile and worker_connections.
  • Docker: set ulimits:nofile in compose or run options.
  • Orchestrators enforce their own limits; review manifests.
# docker-compose.yml (exemplo)
services:
  php-fpm:
    image: php:8.2-fpm
    ulimits:
      nofile:
        soft: 131072
        hard: 131072
  nginx:
    image: nginx:stable
    ulimits:
      nofile:
        soft: 131072
        hard: 131072

Prevention: metrics, logs and load testing

Stabilize operations with visibility and dry runs of peak load. Measure FDs and the FPM queue, centralize logs and test changes before critical hours. Combine FD alerts with traffic charts to anticipate saturation.

Post‑fix checklist

Confirm the new limits are active and that the app sustains the simulated peak. Do not run uncontrolled load tests in production. Use a maintenance window, limits and real‑time monitoring.

  • Unit LimitNOFILE is correct.
  • /proc/$PID/limits reflects the new ceiling.
  • lsof under load stays below the limit.
  • Nginx and containers adjusted as well.
  • Logs show no new 'Too many open files' entries.
systemctl show php-fpm --property=LimitNOFILE 2>/dev/null || \
  systemctl show php8.2-fpm --property=LimitNOFILE 2>/dev/null
PID=$(pgrep -x php-fpm | head -n1)
cat /proc/$PID/limits | grep -i "open files"
# Simule carga leve e observe:
watch -n2 "lsof -p $PID | wc -l"

Frequently asked questions

What causes 'Too many open files' in PHP‑FPM?

The process hit its file descriptor ceiling. This includes sockets, log and temp files. During spikes, each worker holds multiple FDs, summing across the service LimitNOFILE, pool rlimit_files and the kernel fs.file-max.

Is increasing the shell ulimit enough to fix it?

No. Services managed by systemd ignore the ulimit from your interactive session. You must set LimitNOFILE in the service unit and optionally rlimit_files in the PHP‑FPM pool, and ensure an appropriate fs.file-max at the kernel level.

Do I need to restart PHP‑FPM after changing limits?

Yes. Limits like LimitNOFILE and rlimit_files are applied when the process starts. A reload does not change them. Plan a safe restart, draining connections via a reverse proxy to avoid user errors.

What are the risks of setting very high limits?

If limits are raised without matching resources (CPU/RAM/I/O), the server may accept too much work and degrade. The kernel also has a global ceiling (fs.file-max). Increase with reasonable headroom and monitor usage to calibrate.

How do I adjust limits in Docker Compose environments?

Define ulimits:nofile per service in compose or when running containers. Adjust Nginx and PHP‑FPM separately. Host limits are not automatically applied to containers—verify with docker inspect and monitor under load.

Need help stabilizing PHP‑FPM under load?

Guided diagnosis, layered limit adjustments and validations with observability. Let's discuss your environment and practical next steps.

Talk about my environment

See also