← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

nginx + PHP-FPM Production Config

DevOps PHP 5.0+ Intermediate
debt(d7/e5/b5/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The listed tools nginxconfig.io and mozilla-ssl-config can audit some configuration patterns, but the critical misconfigurations — pm.max_children set too high, missing fastcgi_read_timeout, missing pm.max_requests — are not flagged by syntax checkers or default linters. RAM exhaustion and worker swapping only manifest under real production load, making these largely invisible until users hit timeouts or slowdowns.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix shows a single-line fastcgi_pass and SCRIPT_FILENAME fix, but correct remediation spans nginx server blocks, PHP-FPM pool configuration files (pm.max_children, pm.max_requests), php.ini overrides, and timeout settings across both nginx and PHP-FPM. This is multi-file coordination within one component tier, not a one-liner swap.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). The configuration applies only to web PHP contexts but is foundational to the entire web stack's performance behaviour. Any future changes to application load, adding virtual hosts, or scaling workers must revisit these settings. It's a persistent operational tax that shapes capacity planning and incident response, though it doesn't redefine the whole system architecture.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The canonical misconception — 'more PHP-FPM workers always means better performance' — directly contradicts the intuition that more concurrency capacity equals better throughput. This is a documented gotcha that contradicts how horizontal scaling works in other contexts (threads, processes) where adding more workers typically helps. Developers coming from other stacks will reliably guess wrong, setting pm.max_children too high and causing swap-induced collapse under load.

About DEBT scoring →

Also Known As

nginx config PHP-FPM pool fastcgi production PHP setup

TL;DR

The canonical nginx + PHP-FPM setup for PHP production — nginx handles static files and slow clients, PHP-FPM runs PHP via FastCGI, with proper timeout, buffer, and security settings.

Explanation

nginx as a reverse proxy in front of PHP-FPM provides: serving static files directly (no PHP overhead), buffering slow client uploads before passing to FPM (protecting worker count), SSL termination, gzip compression, and security headers. PHP-FPM pool configuration controls worker count, memory limits, and request timeouts. Key settings: pm.max_children (max concurrent PHP processes), pm.max_requests (restart workers after N requests to prevent memory leaks), fastcgi_read_timeout (PHP execution time limit in nginx).

Common Misconception

More PHP-FPM workers always means better performance — each worker consumes ~30-60MB; too many workers exhaust RAM and cause swapping, which is worse than fewer workers.

Why It Matters

A misconfigured nginx/PHP-FPM stack is one of the most common causes of PHP application performance problems — timeouts, worker exhaustion, and memory leaks all stem from missing configuration.

Common Mistakes

  • pm.max_children set too high — workers exceed available RAM, causing swap and severe slowdowns.
  • No fastcgi_read_timeout — nginx kills long-running PHP processes before they complete.
  • Not setting PHP-FPM pm.max_requests — workers accumulate memory leaks without restarts.
  • Missing fastcgi_param PHP_VALUE to override php.ini per virtual host.

Code Examples

✗ Vulnerable
# Minimal nginx config — missing critical settings:
server {
    listen 80;
    root /var/www/html;
    index index.php;
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        # No timeout, no buffering, no security headers
    }
}
; php-fpm.conf — no limits:
pm = dynamic
pm.max_children = 50  ; May exceed available RAM
✓ Fixed
# Production nginx config:
server {
    listen 443 ssl http2;
    root /var/www/html/public;
    
    # Serve static files directly:
    location ~* \.(css|js|png|jpg|woff2)$ {
        expires 1y; add_header Cache-Control 'public, immutable';
    }
    location ~ \.php$ {
        fastcgi_pass unix:/run/php-fpm.sock;
        fastcgi_read_timeout 30;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    }
}
; php-fpm pool.conf:
pm = dynamic
pm.max_children = 20     ; RAM / ~50MB per worker
pm.max_requests = 500     ; Restart after 500 requests

Added 16 Mar 2026
Edited 28 Apr 2026
Views 64
AI edit PF Media Bot Claude Opus 4.5 on bad_code · 28 Apr 2026
Edits history 1 edit
  1. bad_code PF Media Bot Claude Opus 4.5 · 28 Apr 2026
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 2 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 2 pings T 0 pings W 1 ping T 3 pings F 1 ping S 2 pings S 1 ping M 1 ping T 0 pings W 1 ping T 2 pings F 1 ping S 0 pings S 0 pings M 1 ping T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 9 Scrapy 8 SEMrush 7 ChatGPT 7 Perplexity 5 Ahrefs 4 Google 3 Unknown AI 2 Claude 2 Majestic 1 Meta AI 1
crawler 46 crawler_json 3
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Serve PHP via fastcgi_pass unix:/run/php/php8.3-fpm.sock; set fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name to prevent path traversal via Nginx
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name without realpath; missing try_files preventing 404 PHP execution
Auto-detectable: ✓ Yes nginxconfig.io mozilla-ssl-config
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File
CWE-16


✓ schema.org compliant