PHP-FPM Configuration for High-Load 1C-Bitrix

A server with 8 GB RAM and a 4-core CPU under 50 simultaneous users slows down to 5-second response times. `top` shows 95% CPU on php-fpm, swap full. The default PHP-FPM configuration works for simple sites, but not for Bitrix with its heavy ORM and object caches. Under such load, page generation ti

Our competencies:

Frequently Asked Questions

A server with 8 GB RAM and a 4-core CPU under 50 simultaneous users slows down to 5-second response times. top shows 95% CPU on php-fpm, swap full. The default PHP-FPM configuration works for simple sites, but not for Bitrix with its heavy ORM and object caches. Under such load, page generation time can exceed 10 seconds, catastrophically affecting user experience.

We have been configuring PHP-FPM for Bitrix for many years — over 50 projects. During this time, we have developed configurations that handle 200+ simultaneous users on a single server. This article provides specific parameters and calculations for a typical project. Typical cost savings from this optimization range from 30-50% on server resources.

Why Default PHP-FPM Doesn't Fit Bitrix

The default pool usually uses pm = dynamic with pm.max_children = 5. For a Bitrix store with 50 users, this is insufficient — 5 workers get blocked by slow requests, others wait in the queue. Result: Timeout 504. An optimized configuration delivers a 2-3x speed increase over the standard one. With JIT, PHP execution is 10-30% faster compared to no JIT.

How to Calculate the Number of Workers

Formula: max_children = (Available RAM for PHP) / (Average process size). With 8 GB RAM, 2 GB for OS, 1 GB for MySQL: 5 GB / 120 MB ≈ 41. Take a safety margin: 30-35.

RAM server OS + MySQL Available for PHP Process size max_children
8 GB 3 GB 5 GB 120 MB 30-35
16 GB 4 GB 12 GB 120 MB 80-100
32 GB 8 GB 24 GB 120 MB 160-200

Diagnostics of Current State

Before tuning, take a snapshot of the actual picture:

# Number of php-fpm processes and their status ps aux | grep php-fpm | grep -v grep | wc -l # Memory consumption per process ps aux --sort=-%mem | grep php-fpm | head -5 | awk '{print $6/1024 " MB"}' # Pool status via status page curl -s http://127.0.0.1/php-fpm-status?full 

Typical picture: 20-30 PHP-FPM workers consuming 80-150 MB each. 30 * 120 MB = 3.6 GB just for PHP on an 8 GB server.

Pool Configuration

Pool configuration file /etc/php/8.1/fpm/pool.d/bitrix.conf:

[bitrix] user = bitrix group = bitrix listen = /run/php/php8.1-fpm-bitrix.sock listen.owner = www-data listen.group = www-data listen.mode = 0660 ; Process management pm = dynamic pm.max_children = 30 pm.start_servers = 8 pm.min_spare_servers = 5 pm.max_spare_servers = 15 pm.max_requests = 1000 ; Timeouts request_terminate_timeout = 120s request_slowlog_timeout = 5s slowlog = /var/log/php-fpm/slow.log ; Status pm.status_path = /php-fpm-status 

Process management modes: dynamic works for variable load — saves memory during idle but spends resources on fork. static minimizes request delay under stable load but does not adapt to drops. ondemand saves maximum during rare spikes but causes delays on startup. For most Bitrix projects, we choose dynamic. Using static reduces request latency by up to 20% compared to dynamic under consistent load.

pm.max_requests = 1000 — restart worker after 1000 requests prevents memory leaks. Typical for projects with many third-party PHP modules.

How We Configure PHP-FPM Step by Step

  1. Audit current server state using ps, curl pool status.
  2. Calculate pm.max_children based on free memory.
  3. Create separate pools for the site, agents, and 1C import.
  4. Tune php.ini with JIT, Memcached for sessions, OPcache.
  5. Configure slowlog and monitoring.
  6. Test under load.

PHP Configuration for Bitrix

/etc/php/8.1/fpm/php.ini (critical parameters for Bitrix):

; Memory memory_limit = 256M ; Execution time max_execution_time = 90 max_input_time = 60 ; File uploads (for uploading images and price lists) upload_max_filesize = 256M post_max_size = 256M max_file_uploads = 50 ; Sessions session.gc_maxlifetime = 3600 session.save_handler = memcached session.save_path = "127.0.0.1:11211" ; OPcache opcache.enable = 1 opcache.memory_consumption = 256 opcache.max_accelerated_files = 20000 opcache.validate_timestamps = 1 opcache.revalidate_freq = 60 opcache.jit = tracing opcache.jit_buffer_size = 64M ; Disable dangerous functions disable_functions = exec,passthru,shell_exec,system,proc_open,popen 

session.save_handler = memcached — sessions in memory instead of filesystem. Critical for multi-server clusters and speeds up session access by 50x compared to files.

opcache.jit = tracing — JIT compiler for PHP 8.0+. For Bitrix's procedural code, gives 10-30% CPU boost. OPcache stores compiled scripts in shared memory, reducing file I/O.

Comparison of default and optimized PHP parameters:

Parameter Default value Optimized Impact
memory_limit 128M 256M Increase for heavy pages
upload_max_filesize 2M 256M Upload large price lists
session.save_handler files memcached 50x faster session access compared to files
opcache.memory_consumption 128 256 Cache more code

Why Separate Pools for Agents and 1C Import?

It is recommended to separate pools:

  • bitrix.conf — main site, 30 workers, 256M memory
  • agents.conf — Bitrix agents, 3-5 workers, 512M memory, longer timeout
  • import.conf — 1C import, 1-2 workers, 1G memory, 300s timeout

Agents and 1C import should not compete with user requests for workers. Without separation, the import pool can occupy all 30 slots during price list processing.

Monitoring

# Watch status in real time watch -n1 'curl -s http://127.0.0.1/php-fpm-status | grep -E "active|idle|total"' 

If active processes is consistently equal to max_children — the pool is overloaded, requests are queued. You need either increase max_children or optimize code.

Typical PHP-FPM Configuration Mistakes

  • Too small pm.max_children. If max_children is less than the number of concurrent requests, requests queue up. Solution — calculate using the formula above.
  • Missing slowlog. Without slowlog, you won't know which requests are slow. Enable request_slowlog_timeout = 5s.
  • Single pool for all tasks. 1C import and agents should have separate pools, otherwise user requests get blocked.

What's Included in Turnkey Configuration

We offer a comprehensive PHP-FPM optimization service for 1C-Bitrix:

  • Audit of current server and PHP configuration
  • Calculation of optimal worker count and pool sizes
  • Configuration of separate pools for agents and import
  • Optimization of OPcache and JIT
  • Migration of sessions to Memcached or Redis
  • Setup of slowlog and monitoring
  • Configuration documentation
  • Guarantee of stable operation under load

Contact us for a free audit of your PHP-FPM configuration. Order turnkey setup and achieve significant savings on server resources. Savings depend on your server configuration. Our one-time setup fee depends on scope and is typically recouped quickly.

Timeline and Process

Typical timeline: 2–5 business days depending on server complexity.

  • Day 1: Data collection and audit (server specs, current configs, load pattern).
  • Day 2: Analysis and design (calculate workers, plan pool separation, choose caching).
  • Day 3–4: Implementation (configure pools, php.ini, sessions, slowlog, monitoring).
  • Day 5: Load testing, final tuning, and documentation.

Checklist for Self-Check (Optional)

  • Calculate pm.max_children based on free RAM.
  • Set pm.max_requests to 1000 to prevent memory leaks.
  • Enable request_slowlog_timeout and check slowlog daily.
  • Use separate pools for agents and 1C import.
  • Store sessions in Memcached or Redis.
  • Enable OPcache with JIT (PHP 8.0+).
  • Monitor active processes to avoid queue buildup.

Read also read more on Wikipedia and official documentation for in-depth study.