PHP-FPM w hostingu WordPress — konfiguracja, tuning pool-ów i optymalizacja wydajności

Opublikowano: 14 kwietnia 2026 · Autor: Marcin Szewczyk-Wilgan

PHP-FPM (FastCGI Process Manager) to warstwa, która łączy serwer WWW z WordPressem. Każda dynamiczna strona, żądanie AJAX, akcja w panelu administracyjnym i transakcja WooCommerce przechodzi przez PHP-FPM. Źle skonfigurowany PHP-FPM to najczęstsza przyczyna błędów 502/504 i spowolnień WordPress pod obciążeniem. W tym artykule wyjaśniamy, czym jest PHP-FPM, dlaczego zastąpił mod_php, jak prawidłowo skonfigurować pool-e i dyrektywy pm.*, jak diagnozować problemy oraz jak zabezpieczyć PHP-FPM w środowisku produkcyjnym.

Czym jest PHP-FPM i dlaczego zastąpił mod_php

PHP-FPM to osobny demon zarządzający pulą procesów PHP, komunikujący się z serwerem WWW (Nginx lub Apache) przez protokół FastCGI. To standard w nowoczesnym hostingu WordPress — zastąpił starszy mod_php, który ładował interpreter PHP bezpośrednio do procesu Apache.

Definicja

FastCGI Process Manager

PHP-FPM to implementacja FastCGI dla PHP z zaawansowanym zarządzaniem procesami. Utrzymuje pulę gotowych procesów PHP (workerów), które czekają na żądania od serwera WWW. Gdy przychodzi żądanie — wolny worker je przetwarza i zwraca wynik. Gdy worker kończy — wraca do puli. Serwer WWW nie musi wiedzieć nic o PHP — po prostu przekazuje żądanie do socketu PHP-FPM.

Porównanie

PHP-FPM vs mod_php

mod_php ładuje interpreter PHP do każdego procesu Apache — nawet gdy ten serwuje plik CSS. Wynik: ogromne zużycie RAM, brak izolacji, wymuszenie MPM Prefork (najwolniejszego). PHP-FPM to osobny proces — Apache lub Nginx obsługuje połączenia HTTP, a PHP uruchamia się tylko gdy jest potrzebny. Mniej RAM, lepsza izolacja, kompatybilność z MPM Event i Nginx.

Izolacja

Osobne procesy, osobne pool-e

Każda strona WordPress może mieć własny pool PHP-FPM z osobnym użytkownikiem systemowym, limitem pamięci i liczbą workerów. Awaria jednej strony nie wpływa na inne. Włamanie do jednej strony nie daje dostępu do plików innej. To fundament bezpieczeństwa w środowiskach multi-tenant — wielu stron na jednym serwerze.

Kompatybilność

Działa z Nginx i Apache

PHP-FPM jest niezależny od serwera WWW. Nginx komunikuje się przez fastcgi_pass (unix socket lub TCP). Apache — przez mod_proxy_fcgi z SetHandler lub ProxyPassMatch. W konfiguracji reverse proxy PHP-FPM to backend, który obsługuje wyłącznie żądania PHP — resztę (pliki statyczne, SSL) obsługuje serwer WWW.

Konfiguracja pool-ów PHP-FPM pod WordPress

Pool to niezależna pula procesów PHP-FPM z własną konfiguracją. Każda strona WordPress powinna mieć osobny pool — dla izolacji zasobów, bezpieczeństwa i możliwości niezależnego tuningu. Pliki konfiguracyjne pool-ów znajdują się zwykle w /etc/php/8.x/fpm/pool.d/.

Pool per stronaOsobny plik .conf per stronę WordPress (np. example-com.conf). Każdy pool działa pod osobnym użytkownikiem systemowym (user = example, group = example). Izolacja: użytkownik jednej strony nie może czytać ani modyfikować plików innej. Awaria PHP w jednym pool-u nie wpływa na pozostałe.
pm static / dynamic / ondemandpm = static — stała liczba workerów, najszybszy czas odpowiedzi, stałe zużycie RAM. Najlepszy dla serwerów dedykowanych z przewidywalnym ruchem. pm = dynamic — automatyczne skalowanie workerów, optymalny dla większości stron WordPress. pm = ondemand — workery tworzone tylko na żądanie, minimalne zużycie RAM, lekkie opóźnienie przy pierwszym żądaniu. Najlepszy dla wielu stron o niskim ruchu.
pm.max_childrenMaksymalna liczba jednoczesnych workerów PHP. Formuła: (RAM dostępny dla PHP-FPM) / (średni rozmiar procesu PHP). Zmierz rozmiar procesu: ps -ylC php-fpm --sort:rss. Typowy proces WordPress: 40–80 MB. Dla WooCommerce: 60–120 MB. Przykład: 4 GB RAM, 2 GB dla PHP-FPM, proces ~60 MB → pm.max_children = 30. Zawsze zostawiaj 15–20% bufora.
pm.start_servers / min_spare / max_spareTylko dla pm = dynamic. pm.start_servers — ile workerów uruchomić na starcie (~25% max_children). pm.min_spare_servers — minimum wolnych workerów (~10–15% max_children). pm.max_spare_servers — maximum wolnych workerów (~35% max_children). PHP-FPM automatycznie tworzy i zabija workery w tych granicach.
Unix socket vs TCPUnix socket (listen = /run/php/php8.4-fpm-example.sock) jest szybszy niż TCP (listen = 127.0.0.1:9000) — eliminuje overhead stosu sieciowego. Używaj socket-ów gdy serwer WWW i PHP-FPM są na tym samym serwerze. TCP tylko gdy PHP-FPM działa na osobnej maszynie. Uprawnienia socketu muszą zgadzać się z użytkownikiem serwera WWW (www-data).
pm.max_requests i slowlogpm.max_requests = 500 — po 500 żądaniach worker jest restartowany. Zapobiega wyciekowi pamięci z wtyczek WordPress, które nie zwalniają zasobów poprawnie. slowlog = /var/log/php-fpm/example-slow.log z request_slowlog_timeout = 5s — loguje stack trace żądań trwających dłużej niż 5 sekund. Najlepsza metoda znajdowania wolnych wtyczek i zapytań.

Tuning PHP-FPM — jak dobrać parametry do serwera

Domyślne ustawienia PHP-FPM (pm.max_children = 5 na wielu dystrybucjach) są zaprojektowane pod bezpieczeństwo, nie wydajność. Na serwerze z 4 GB RAM domyślna konfiguracja wykorzystuje zaledwie 10–15% dostępnej mocy. Tuning wymaga pomiarów — nie zgadywania.

RAM

Obliczanie RAM per proces

Komenda ps -ylC php-fpm --sort:rss pokazuje RSS (Resident Set Size) każdego workera w KB. Typowy worker WordPress: 40–80 MB. WooCommerce z rozbudowanymi wtyczkami: 60–120 MB. Ciężkie wtyczki (page buildery, membership) mogą podnosić zużycie do 150+ MB. Mierz pod realnym obciążeniem, nie na pustym serwerze.

Formuła

pm.max_children a OOM killer

Zbyt wysoki pm.max_children → serwer wchodzi w swap → dramatyczne spowolnienie → OOM killer zabija procesy (często MySQL, nie PHP-FPM). Zbyt niski → żądania czekają w kolejce → błędy 502/504. Formuła: (RAM serwera − RAM system − RAM MySQL − RAM serwer WWW) / RAM per worker × 0.85 (bufor). Monitoruj po wdrożeniu i koryguj.

Monitoring

pm.status_path — monitoring w czasie rzeczywistym

Dyrektywa pm.status_path = /php-fpm-status w pool-u + blok location w Nginx (ograniczony do localhost). Pokazuje: aktywne procesy, idle procesy, max children reached (ile razy osiągnięto limit), listen queue (ile żądań czeka). Jeśli max children reached > 0 — trzeba zwiększyć pm.max_children lub zoptymalizować PHP.

OPcache

OPcache — wpływ na PHP-FPM

OPcache przechowuje skompilowany bytecode PHP w pamięci współdzielonej — workery nie muszą parsować plików PHP przy każdym żądaniu. Skraca czas wykonania o 50–70%. Szybszy worker = szybciej zwalnia slot = więcej żądań przy tej samej liczbie workerów. opcache.memory_consumption = 128 i opcache.max_accelerated_files = 10000 to dobry punkt startowy dla WordPress. Więcej o wersji PHP w artykule WordPress a wydajność PHP.

JIT

JIT w PHP 8.x — kiedy pomaga

JIT (Just-In-Time compilation) w PHP 8.0+ kompiluje bytecode do kodu maszynowego w runtime. Dla typowego WordPressa (operacje I/O: baza danych, HTTP) zysk jest minimalny — JIT pomaga przy operacjach CPU-intensive. Dla WooCommerce z ciężkimi kalkulacjami (rabaty, podatki, shipping) i stronach z dużą ilością logiki PHP — JIT może skrócić czas wykonania o 5–15%.

Object cache

Redis/Memcached — odciążenie PHP-FPM

WordPress wykonuje dziesiątki zapytań SQL per żądanie. Object cache (Redis lub Memcached) przechowuje wyniki zapytań w pamięci — worker PHP-FPM pobiera dane z cache zamiast odpytywać bazę. Krótszy czas wykonania żądania = worker szybciej wraca do puli = mniej potrzebnych workerów. Redis z wtyczką Redis Object Cache to standard na profesjonalnych hostingach WordPress.

PHP-FPM z Nginx vs PHP-FPM z Apache

PHP-FPM jest niezależny od serwera WWW, ale integracja z Nginx i Apache różni się konfiguracją i subtelnymi różnicami wydajnościowymi.

Nginx + fastcgi_passNginx komunikuje się z PHP-FPM przez fastcgi_pass unix:/run/php/php8.4-fpm.sock; w bloku location ~ \.php$. Nginx obsługuje pliki statyczne bezpośrednio, a do PHP-FPM przekazuje tylko żądania PHP. Natywne wsparcie FastCGI cache (fastcgi_cache) pozwala serwować odpowiedzi PHP z cache Nginx bez angażowania PHP-FPM.
Apache + mod_proxy_fcgiApache używa SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost" lub ProxyPassMatch. Wymaga włączenia mod_proxy i mod_proxy_fcgi. Pozwala na MPM Event zamiast Prefork (mod_php wymusza Prefork). Apache z PHP-FPM i MPM Event osiąga porównywalną wydajność z Nginx dla typowego ruchu WordPress.
Socket vs TCP — różniceUnix socket jest szybszy o ~5–10% niż TCP loopback (127.0.0.1:9000) — eliminuje overhead stosu TCP/IP. Różnica mierzalna przy dużym ruchu. TCP jest konieczny gdy PHP-FPM działa na osobnym serwerze (rozproszony setup). Na jednym serwerze — zawsze socket. Uprawnienia: listen.owner = www-data musi zgadzać się z użytkownikiem Nginx/Apache.
Wspólne pułapkiNiedopasowanie ścieżki socketu (serwer WWW wskazuje na inny socket niż PHP-FPM nasłuchuje) → 502. Brak uprawnień do socketu → 502. Różna wersja PHP w ścieżce socketu po aktualizacji PHP (np. socket php8.3-fpm.sock po upgrade do PHP 8.4) → 502. Zawsze weryfikuj ścieżkę socketu po każdej aktualizacji PHP.

Diagnostyka problemów PHP-FPM

Błędy 502 i 504 to najczęstsze objawy problemów z PHP-FPM. Diagnostyka wymaga sprawdzenia logów, statusu pool-u i zużycia zasobów. Poniżej najczęstsze problemy i ich rozwiązania.

502 Bad GatewaySerwer WWW nie może połączyć się z PHP-FPM. Przyczyny: PHP-FPM nie działa (systemctl status php8.4-fpm), błędna ścieżka socketu w konfiguracji serwera WWW, brak uprawnień do socketu, lub PHP-FPM crashnął (sprawdź /var/log/php8.4-fpm.log). Najszybsza diagnostyka: ls -la /run/php/ — sprawdź czy socket istnieje i ma właściwe uprawnienia.
504 Gateway TimeoutŻądanie PHP trwa dłużej niż timeout serwera WWW. Przyczyny: wolne zapytania SQL, ciężkie wtyczki (np. backup w tle, importy), zbyt niski max_execution_time w php.ini, lub request_terminate_timeout w pool-u PHP-FPM. Rozwiązanie: sprawdź slowlog PHP-FPM, slow query log MySQL i dostosuj timeout-y. Nie podnoś timeout-ów bezkrytycznie — to maskuje prawdziwy problem.
"server reached pm.max_children"Komunikat w logu PHP-FPM oznaczający, że wszystkie workery są zajęte i nowe żądania czekają w kolejce. Rozwiązanie: zwiększ pm.max_children (jeśli masz zapas RAM), zoptymalizuj PHP (OPcache, object cache, szybsza baza danych) lub zmniejsz czas wykonania żądania. Sprawdź pm.status_path — ile razy limit został osiągnięty i jaka jest długość kolejki.
Wysokie zużycie RAMProcesy PHP-FPM rosną w pamięci z czasem (memory leak we wtyczkach). pm.max_requests = 500 restartuje workera po 500 żądaniach — zwalnia skumulowaną pamięć. Jeśli pojedynczy worker zużywa ponad 150 MB — szukaj ciężkiej wtyczki (page builder, membership, backup). Komenda ps -o pid,rss,command -C php-fpm --sort=-rss pokazuje workerów posortowanych po zużyciu RAM.
Slowlog — wolne skryptyslowlog w konfiguracji pool-u loguje stack trace żądań przekraczających request_slowlog_timeout. Pokazuje dokładnie, jaka funkcja PHP w jakiej wtyczce jest odpowiedzialna za spowolnienie. To najskuteczniejsze narzędzie diagnostyczne PHP-FPM — wskazuje wprost na winowajcę, zamiast zmuszać do zgadywania.

Bezpieczeństwo PHP-FPM

PHP-FPM to punkt, w którym kod PHP — w tym kod wtyczek i motywów WordPress — jest faktycznie wykonywany. Prawidłowa konfiguracja bezpieczeństwa PHP-FPM minimalizuje skutki ewentualnego włamania na jedną ze stron na serwerze.

Osobny user per poolKażdy pool PHP-FPM działa pod osobnym użytkownikiem systemowym (user = site1, group = site1). Pliki WordPress należą do tego użytkownika. Wynik: PHP jednej strony nie może czytać ani modyfikować plików innej strony na tym samym serwerze. To najbardziej fundamentalne zabezpieczenie w środowiskach multi-site.
open_basedirDyrektywa php_admin_value[open_basedir] = /var/www/site1:/tmp w pool-u ogranicza dostęp PHP do wskazanych katalogów. Nawet jeśli atakujący uzyska zdalne wykonanie kodu — nie może czytać plików spoza katalogu strony. Nie może odczytać /etc/passwd, plików innych stron ani konfiguracji serwera.
disable_functionsphp_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen — wyłącza funkcje PHP pozwalające na wykonywanie komend systemowych. WordPress nie potrzebuje ich do normalnego działania. Blokuje typowy payload atakujących — nawet po wgraniu webshella, nie mogą uruchomić komend na serwerze. Uwaga: niektóre wtyczki backupowe mogą wymagać exec.
chroot (zaawansowane)Dyrektywa chroot = /var/www/site1 izoluje cały proces PHP-FPM w katalogu strony — PHP nie widzi reszty systemu plików. Najsilniejsza izolacja, ale wymaga dostępności bibliotek, plików konfiguracyjnych i ścieżek socket-ów wewnątrz chroot. Bardziej złożona w konfiguracji niż open_basedir, ale oferuje izolację na poziomie systemu operacyjnego.

Podsumowanie

PHP-FPM to fundament wydajności WordPress — warstwa, która bezpośrednio odpowiada za czas generowania każdej dynamicznej strony. Domyślne ustawienia PHP-FPM są zaprojektowane pod bezpieczeństwo, nie wydajność — tuning pm.max_children, wybór trybu pm (dynamic/static/ondemand) i konfiguracja OPcache mogą kilkukrotnie zwiększyć liczbę obsługiwanych żądań. Osobne pool-e per strona, open_basedir i disable_functions zapewniają izolację i bezpieczeństwo. Diagnostyka przez pm.status_path i slowlog pozwala znajdować problemy zanim wpłyną na użytkowników.

W WebOptimo konfigurujemy i tunujemy PHP-FPM pod WordPress i WooCommerce w ramach administracji serwerami i hostingu WordPress. Dobieramy parametry pool-ów do zasobów serwera, wdrażamy OPcache i Redis, diagnozujemy problemy wydajnościowe przez slowlog i monitoring. Jeśli Twoja strona spowalnia pod ruchem lub widzisz błędy 502/504 — skontaktuj się z nami lub sprawdź ofertę opieki WordPress.

Najczęstsze pytania o PHP-FPM i WordPress

mod_php ładuje interpreter PHP bezpośrednio do procesu Apache — każdy proces Apache zawiera pełny interpreter PHP, nawet obsługując pliki statyczne. PHP-FPM to osobny demon zarządzający pulą procesów PHP, komunikujący się z serwerem WWW przez protokół FastCGI. PHP-FPM pozwala na izolację procesów, osobne pool-e per strona, lepsze zarządzanie pamięcią i kompatybilność z Nginx oraz Apache MPM Event.

Zmierz średnie zużycie RAM jednego procesu PHP-FPM poleceniem ps. Odejmij od całkowitego RAM serwera pamięć potrzebną dla systemu, bazy danych i serwera WWW. Podziel dostępny RAM przez średni rozmiar procesu PHP. Zostaw 15–20% bufora bezpieczeństwa. Przykład: 4 GB RAM, 1.5 GB na system/MySQL/Nginx, proces ~60 MB → pm.max_children ≈ 35.

Błąd 502 oznacza, że serwer WWW (Nginx lub Apache) nie może połączyć się z PHP-FPM. Najczęstsze przyczyny: PHP-FPM nie działa, błędna ścieżka do socketu, uprawnienia socketu uniemożliwiające połączenie, lub wszystkie workery PHP-FPM są zajęte i nowe żądania nie mogą być obsłużone. Sprawdź status PHP-FPM i czy socket istnieje.

Dynamic to optymalny wybór dla większości stron WordPress — automatycznie skaluje liczbę workerów w zależności od ruchu. Static jest najlepszy dla serwerów dedykowanych z przewidywalnym, stałym ruchem. Ondemand sprawdza się na serwerach z wieloma stronami o niskim ruchu — workery są tworzone tylko gdy potrzebne i zwalniane po okresie bezczynności.

Tak. Nginx komunikuje się z PHP-FPM przez dyrektywę fastcgi_pass. Apache — przez mod_proxy_fcgi z dyrektywą SetHandler lub ProxyPassMatch. PHP-FPM jest niezależny od serwera WWW — to osobny proces, który może obsługiwać żądania z dowolnego serwera wspierającego protokół FastCGI.

Porozmawiajmy o wydajności PHP-FPM na Twoim serwerze

Przeanalizujemy konfigurację PHP-FPM i zaproponujemy konkretne działania — od tuningu pool-ów przez wdrożenie OPcache i Redis po diagnostykę błędów 502/504. Bez zobowiązań, bez marketingowego żargonu — konkretna propozycja po krótkiej rozmowie lub analizie witryny.

Telefon

+48 608 271 665

Pn–Pt, 8:00–16:00

E-mail

kontakt@weboptimo.pl

Odpowiadamy w ciągu 24h

Firma

WebOptimo

NIP: 6391758393