Błąd 504 Gateway Timeout znaczy, że serwer stojący przed PHP (nginx, CDN albo proxy hostingu) nie dostał odpowiedzi w wyznaczonym czasie. WordPress zwykle nie jest tu sprawcą, tylko ofiarą: żądanie czeka w kolejce na wolnego workera PHP albo samo trwa za długo. Zacznij od logów PHP-FPM z godziny awarii, potem sprawdź, czy błąd dotyczy całej strony czy jednego adresu.
Co oznacza błąd 504 w WordPressie
MDN, za RFC 9110, definiuje 504 jako sytuację, w której serwer działający jako brama lub proxy “nie otrzymał na czas odpowiedzi od serwera nadrzędnego” (tłumaczenie własne). Różni się to od 502 Bad Gateway: tam odpowiedź przyszła, ale była nieprawidłowa. W 504 nie przyszło nic.
Na typowym hostingu WordPressa łańcuch wygląda tak: przeglądarka, opcjonalnie CDN, nginx, PHP-FPM, baza danych i ewentualnie cache obiektowy. Kod 504 generuje ogniwo, które czekało. Samo to mówi, gdzie szukać. Jeśli nginx czeka na PHP, problem leży w PHP, bazie albo w kolejce do PHP. Jeśli czeka CDN, problem leży w serwerze źródłowym.
Dokumentacja MDN zaznacza też, że przyczyn jest wiele i naprawa zwykle wymaga analizy po stronie administratora serwera. Dlatego dalej nie ma jednej magicznej poprawki, jest kolejność kontroli.
Czy 504 to wina hostingu, czy strony
Pytanie rozstrzyga zakres błędu. Poniższa tabela to skrót decyzyjny, nie wyrok.
| Objaw | Najbardziej prawdopodobny kierunek |
|---|---|
| 504 na całej stronie, także na prostych podstronach | Za mało workerów PHP albo przeciążony serwer: hosting lub ruch |
| 504 tylko na jednym adresie | Wolne zapytanie, wtyczka albo zewnętrzne API wywoływane przez ten adres |
| 504 w wp-admin i przy zapisie, front działa z cache | Ciężkie żądania zalogowanych użytkowników, które omijają cache |
| 504 sporadycznie, w tych samych godzinach | Zadania cykliczne, kopie zapasowe albo szczyt ruchu |
| 504 po zmianie wtyczki lub aktualizacji | Konflikt wtyczki albo migracja bazy, która trwa za długo |
Odpowiedzialność hostingu zaczyna się tam, gdzie limity (liczba workerów, pamięć, CPU) są za małe na normalny ruch strony. Odpowiedzialność strony zaczyna się tam, gdzie pojedyncze żądanie robi tyle pracy, że blokuje workera na dziesiątki sekund. W praktyce często działa oba naraz: wolne żądania zajmują workerów, a mała pula nie ma zapasu.
Dlaczego strona na WordPressie co kilka tygodni przestaje działać
W listopadzie 2025 roku na forum r/webdev właściciel dwóch stron na WordPressie, obsługiwanych przez tego samego programistę, zapytał wprost, czy to normalne:
Co kilka tygodni strony nagle przestają działać albo coś się psuje: albo strona się nie ładuje, albo coś przestaje działać. Programista zawsze mówi, że to problem z hostingiem albo że trzeba odnowić, zrobić kopię albo aktualizację, a potem proponuje roczny plan opieki albo kopii zapasowych za dodatkową opłatą.
(tłumaczenie własne, r/webdev, wątek z 2 listopada 2025)
Wątek zebrał kilkadziesiąt odpowiedzi. Poniżej pytania, które z niego wynikają, i to, co da się sprawdzić samemu.
Czy to wina hostingu, czy programisty
Odpowiedzi w wątku rozjechały się na dwa obozy. Jeden z programistów, który monitoruje strony wszystkich swoich klientów, pisze, że strony na tańszym hostingu “przestają działać co najmniej raz w tygodniu”, bo nie wytrzymują ruchu botów (tłumaczenie własne, tomhermans, r/webdev). Inny odpowiada, że poprawnie skonfigurowana strona na dobrym hostingu “praktycznie nigdy nie powinna paść” (tłumaczenie własne, redlotusaustin, r/webdev).
Obie rzeczy mogą być prawdą jednocześnie, a tabela wyżej pomaga je rozdzielić. Jeśli przy każdej awarii widać 502 albo 504 na całej stronie, winne są zwykle zasoby: za mała pula PHP-FPM albo przeciążony serwer współdzielony. Jeśli strona psuje się w jednym miejscu, a reszta działa, przyczyna leży w kodzie, wtyczce albo motywie.
Czy boty mogą położyć stronę WordPress na tanim hostingu
Mogą. Bot, który przechodzi po adresach bez cache, uruchamia PHP przy każdym żądaniu. Na hostingu współdzielonym z kilkoma workerami PHP kolejka szybko się zapełnia i kolejne żądania kończą się błędem 504, opisanym w sekcjach niżej. Pomaga cache stron przed PHP (na serwerze albo w CDN) i ograniczanie liczby żądań od jednego klienta. Przy blokowaniu botów w Cloudflare uważaj na opcję, która odcina też Googlebota, co opisaliśmy we wpisie czy Cloudflare blokuje Googlebota.
Czy aktualizacje wtyczek psują stronę WordPress
Jeden z uczestników wątku wskazuje aktualizacje wtyczek jako częsty powód awarii, gdy wgrywa się je od razu na działającą stronę, bez testu na stagingu (tłumaczenie własne, technomalist, r/webdev). Jeśli awarie pokrywają się w czasie z aktualizacjami, porównaj daty awarii z historią aktualizacji. Sposób pracy z kopią testową opisuje nasz przewodnik po stagingu WordPressa.
Czy powtarzające się awarie mogą oznaczać włamanie
Mogą. W wątku pada opis typowego cyklu: strona zainfekowana przez podatną wtyczkę zostaje przywrócona z kopii zapasowej, ale luka zostaje otwarta, więc po kilku dniach wszystko się powtarza (tłumaczenie własne, 30thnight, r/webdev). Przywrócenie kopii bez usunięcia przyczyny nie kończy problemu. Kroki czyszczenia opisuje przewodnik po usuwaniu malware z WordPressa.
Jak samemu sprawdzić, dlaczego strona padła
Najkrótsza odpowiedź w wątku brzmi: “Co mówią logi?” (tłumaczenie własne, chmod777, r/webdev). Właściciel strony może to zrobić bez programisty:
- Włącz zewnętrzny monitoring dostępności, który zapisuje godzinę i czas trwania każdej awarii.
- Miej własny dostęp do panelu hostingu, a nie tylko do panelu WordPressa.
- Po awarii otwórz log błędów PHP i log błędów serwera WWW z tej samej godziny. Błędy krytyczne PHP wskazują na kod albo wtyczkę, przekroczone limity procesów i timeouty na zasoby hostingu.
- Porównaj godziny awarii z datami aktualizacji wtyczek, motywu i WordPressa.
Czy płatny plan opieki nad stroną WordPress ma sens
Plan opieki opłaca regularną pracę: aktualizacje testowane przed wdrożeniem, monitoring, kopie zapasowe i reakcję na awarie. Nie powinien jednak być odpowiedzią na awarie, których przyczyny nikt nie nazwał. Awaria co kilka tygodni nie jest normalna ani z planem, ani bez niego. Przy każdej awarii warto dostać na piśmie przyczynę i to, co zmieniono, żeby się nie powtórzyła. Tak pracujemy w ramach opieki technicznej nad stronami WordPress.
Jak sprawdzić, gdzie żądanie utknęło
Zacznij od trzech miejsc, w tej kolejności.
- Log błędów serwera WWW z godziny awarii. W nginx wpis
upstream timed outpotwierdza, że serwer czekał na PHP. - Log PHP-FPM. Komunikat o osiągnięciu
pm.max_childrenoznacza, że pula była pełna i kolejne żądania stały w kolejce. Opcjapm.max_children, jak opisuje dokumentacja PHP, wyznacza limit jednoczesnych żądań obsługiwanych przez pulę. - Log WordPressa. Ustaw w
wp-config.phpWP_DEBUGnatrue,WP_DEBUG_LOGnatrueiWP_DEBUG_DISPLAYnafalse. Błędy trafią dowp-content/debug.logzamiast na ekran. Tak opisuje to dokumentacja WordPressa. Wyłącz debug po diagnozie.
Gdy hosting daje dostęp do slowloga PHP-FPM, ustaw request_slowlog_timeout, a PHP zapisze backtrace żądań, które trwają dłużej niż limit. Domyślnie opcja jest wyłączona (wartość 0). Backtrace pokazuje, w której funkcji wtyczki albo motywu PHP czekał.
Na hostingu współdzielonym często nie ma dostępu do tych logów. Wtedy dostęp do nich i do metryk puli PHP to pierwsza rzecz, o którą trzeba poprosić support, razem z godziną awarii i adresem, który zwrócił 504.
Dlaczego zbyt mała pula PHP-FPM daje 504
Każde żądanie dynamiczne zajmuje jednego workera PHP-FPM do końca odpowiedzi. Gdy wszyscy workerzy są zajęci, nowe żądania czekają. Jeśli czekają dłużej niż limit proxy, odwiedzający widzi 504.
Domyślny fastcgi_read_timeout w nginx wynosi 60 sekund, a dokumentacja nginx zaznacza, że limit liczy się między dwoma kolejnymi odczytami z serwera FastCGI, nie dla całej odpowiedzi. Na hostingach zarządzanych wartość bywa inna, więc nie zakładaj, że u Ciebie to akurat 60 sekund.
Podniesienie pm.max_children pomaga tylko wtedy, gdy serwer ma na to pamięć. Każdy worker WordPressa z kilkoma wtyczkami zajmuje jej wyraźny kawałek, więc zbyt wysoka wartość kończy się wyczerpaniem RAM i zabijaniem procesów, czyli gorszym stanem niż kolejka. Konfiguracja puli to zadanie dla administratora, który widzi zużycie pamięci.
Jak wolne zapytania i autoloadowane opcje powodują 504
Gdy 504 dotyczy całej strony, a pula nie jest pełna od ruchu, sprawdź bazę. Dokumentacja WordPressa zwraca uwagę, że WordPress powtarza wiele zapytań przy każdym żądaniu, a opcje oznaczone jako autoload wczytują się przy każdym wejściu. Zaleca trzymanie ich poniżej 800 KB, a pełne zalecenia opisano w poradniku optymalizacji. Wtyczka, która zapisuje duże dane w wp_options z autoloadem, wpycha je do każdego żądania. Rozmiar autoloadu sprawdzisz zapytaniem SQL po kolumnie autoload w tabeli opcji.
Do namierzenia wolnych zapytań służy stała SAVEQUERIES. Zapisuje ona każde zapytanie, czas wykonania i funkcję, która je wywołała, w $wpdb->queries. Kosztuje wydajność, więc włącz ją na krótko i na stagingu, jeśli to możliwe.
Kiedy cache obiektowy i Redis powodują 504
Trwały cache obiektowy zmniejsza liczbę zapytań do bazy i zwykle przyspiesza stronę. Wymaga jednak działającego serwera cache oraz pliku drop-in wp-content/object-cache.php.
Awaria działa w drugą stronę, gdy ten plik istnieje, a serwer Redis nie odpowiada. Każde żądanie próbuje wtedy połączyć się z cache, czeka na timeout połączenia i dopiero potem idzie dalej albo się poddaje. Objaw to 504 zaraz po restarcie albo awarii usługi cache po stronie hostingu, mimo że sam kod strony się nie zmienił.
Test jest prosty: zmień nazwę object-cache.php na inną. Jeśli 504 znika, winny jest cache, a nie WordPress. Przywróć plik dopiero po naprawie usługi.
Jak WP-Cron, admin-ajax i zewnętrzne API wywołują 504
Trzy źródła pojedynczych, wolnych żądań warto sprawdzić osobno.
- WP-Cron. Dokumentacja WordPressa wyjaśnia, że WP-Cron uruchamia się przy wejściu na stronę, nie jako stały proces. Zaległe, ciężkie zadania (kopie zapasowe, import, wysyłka) mogą więc obciążyć zwykłe żądanie odwiedzającego. Przeniesienie wywołań na systemowego crona hostingu odciąża front.
- admin-ajax.php. Wtyczki wysyłają tu żądania z panelu i z frontu. Jeśli 504 pojawia się właśnie tu, szukaj wtyczki, która robi ciężką operację w tle.
- Zewnętrzne API. Wtyczka czekająca na wolny system zewnętrzny (płatności, ERP, wysyłka) trzyma workera tak długo, jak on odpowiada. Brak własnego, krótkiego timeoutu w tej wtyczce zamienia cudzą awarię w Twoje 504.
Czym różni się 504 od 502 i 524
- 502 Bad Gateway: serwer za proxy odpowiedział, ale odpowiedź była nieprawidłowa. Często to padnięty proces PHP-FPM.
- 504 Gateway Timeout: brak odpowiedzi w czasie. Najczęściej przeciążenie lub wolne żądanie.
- 524: kod Cloudflare. Dokumentacja Cloudflare podaje, że pojawia się, gdy serwer źródłowy nie odpowie w domyślnych 125 sekundach. Cloudflare radzi poprosić hosting o sprawdzenie długich procesów i przeciążenia, a duże operacje przenieść na kanał bez proxy.
Za CDN-em możesz więc zobaczyć dwa różne kody dla tej samej przyczyny, zależnie od tego, które ogniwo pierwsze straciło cierpliwość.
Kiedy podnosić timeout, a kiedy nie
Podniesienie fastcgi_read_timeout albo limitu czasu PHP jest uzasadnione dla jednej, świadomie długiej operacji, na przykład ręcznego importu. Dla strony, która wyświetla 504 odwiedzającym, to maskowanie: wolne żądanie nadal zajmuje workera, tylko dłużej, a pula zapełnia się szybciej.
PHP-FPM ma osobny bezpiecznik, request_terminate_timeout. Dokumentacja opisuje go jako limit, po którym proces obsługujący żądanie jest zabijany, i podaje domyślną wartość 0, czyli wyłączony. Ustawiony rozsądnie, zabezpiecza pulę przed jednym zawieszonym skryptem.
Aktualizacja, . Długie zadania w panelu, takie jak kopia zapasowa albo eksport bazy danych, to typowa przyczyna 504 na hostingu współdzielonym. Na takim planie zwykle nie zmienisz limitu proxy, a proxy zamyka żądanie, zanim PHP skończy pracę, bez względu na wartość max_execution_time. Rozwiązaniem jest podział zadania na krótkie żądania, które da się wznowić. Widać to na przykładzie naszej wtyczki Migrator. Od wersji 1.6.0 kopia zapasowa uruchomiona z wp-admin eksportuje bazę danych etapami, po porcji wierszy na żądanie, więc duża baza eksportuje się bez błędu 504 Gateway Timeout na hostingu współdzielonym. Przerwany etap rusza od miejsca, w którym zatrzymał się poprzedni, a filtr migrator_step_seconds ustala, jak długo może trwać jeden etap, na hostingach, których proxy wcześnie ucina żądania. Jeśli eksport albo import we wtyczce pada z 504 za każdym razem w podobnym momencie, poszukaj trybu, który dzieli pracę na porcje i umie ją wznowić, albo poleceń WP-CLI (Migrator ma polecenia wp migrator od wersji 1.5.0). Podnoszenie limitów PHP nic tu nie da, bo proxy ich nie bierze pod uwagę.
Które timeouty nginx kończą się błędem 504
Moduł FastCGI w nginx ma trzy osobne liczniki czasu i każdy z nich domyślnie wynosi 60 sekund, co podaje dokumentacja modułu ngx_http_fastcgi_module.
| Dyrektywa | Co mierzy | Domyślnie |
|---|---|---|
fastcgi_connect_timeout | nawiązanie połączenia z PHP-FPM | 60 s, zwykle nie więcej niż 75 s |
fastcgi_send_timeout | przerwę między dwoma kolejnymi zapisami żądania do PHP-FPM | 60 s |
fastcgi_read_timeout | przerwę między dwoma kolejnymi odczytami odpowiedzi | 60 s |
Dwa ostatnie liczniki zerują się przy każdej porcji danych. Skrypt, który co jakiś czas coś wysyła, może więc pracować dłużej niż minutę bez błędu. Skrypt, który milczy, bo czeka na bazę albo na zewnętrzne API, dostaje 504 po 60 sekundach. fastcgi_send_timeout ma znaczenie głównie przy dużych żądaniach POST, na przykład przy wgrywaniu pliku albo imporcie.
Gdy nginx stoi przed Apache, a nie bezpośrednio przed PHP-FPM, liczy się proxy_read_timeout z modułu ngx_http_proxy_module. Też ma 60 sekund i też mierzy przerwę między odczytami, nie całą odpowiedź.
Wszystkie te dyrektywy działają w kontekście http, server i location. Wyższy limit da się więc ustawić tylko dla jednej ścieżki, która go naprawdę potrzebuje, zamiast dla całego serwera:
location = /wp-admin/admin-ajax.php {
# wyższy limit tylko tutaj, reszta serwera zostaje przy 60 s
fastcgi_read_timeout 120s;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}Ścieżka do gniazda PHP-FPM różni się między dystrybucjami i hostingami, więc przepisz ją z istniejącej konfiguracji, a nie z przykładu.
Timeout w Apache z PHP-FPM i mod_proxy_fcgi
Apache przekazuje PHP do PHP-FPM przez mod_proxy_fcgi, zwykle dyrektywą SetHandler "proxy:unix:/ścieżka/do/gniazda.sock|fcgi://localhost/". Czas oczekiwania wyznaczają tu trzy ustawienia, które dziedziczą po sobie wartość:
Timeoutz rdzenia Apache, domyślnie 60 sekund. Dokumentacja Apache podaje, że wmod_proxyjest to wartość domyślna, jeśli nie ustawionoProxyTimeout.ProxyTimeoutz mod_proxy, domyślnie równyTimeout. Dokumentacja opisuje go jako sposób na zwrócenie błędu timeoutu, gdy serwer aplikacji się zawiesza, zamiast czekania bez końca.- parametr
timeoutprzyProxyPassalbo w definicji workera, domyślnie równyProxyTimeout. To liczba sekund, przez które Apache czeka na dane wysyłane do backendu albo z niego.
Wszystkie trzy mają kontekst server config i virtual host, więc nie zadziałają w .htaccess. Na hostingu współdzielonym zmienić je może tylko administrator serwera.
Dlaczego max_execution_time nie chroni przed 504
max_execution_time w PHP domyślnie wynosi 30 sekund, czyli mniej niż 60 sekund nginx. Wydaje się więc, że PHP zawsze przerwie skrypt, zanim proxy zwróci 504. Tak nie jest. Dokumentacja PHP podaje, że w systemach innych niż Windows na ten limit nie wpływają wywołania systemowe i operacje na strumieniach. Opis funkcji set_time_limit() dopowiada, że do czasu skryptu nie wlicza się też zapytań do bazy danych.
W praktyce żądanie WordPressa, które 70 sekund czeka na zablokowaną tabelę MySQL albo na odpowiedź bramki płatności, nie przekroczy limitu PHP. Worker zostaje zajęty, a nginx po 60 sekundach ciszy oddaje 504. Wyjątkiem są kompilacje PHP z opcją --enable-zend-max-execution-timers (domyślną dla kompilacji ZTS od PHP 8.3.0): tam limit mierzy upływ czasu, łącznie z czekaniem na wejście i wyjście.
Dlatego przy zewnętrznych API liczy się timeout samego połączenia. Funkcje HTTP WordPressa (WP_Http::request) mają domyślny timeout 5 sekund, zmieniany filtrem http_request_timeout. Wtyczka, która podnosi tę wartość do minuty, zdejmuje zabezpieczenie i to ona zamienia wolne API w 504.
Z tych liczb wynika kolejność, która ułatwia diagnozę: limit wewnętrzny krótszy od zewnętrznego. Timeout połączenia HTTP we wtyczce (5 s) poniżej limitu PHP (30 s), ten poniżej fastcgi_read_timeout (60 s), a ten poniżej 125 sekund Cloudflare. Gdy wewnętrzny limit zadziała pierwszy, błąd trafia do debug.log z nazwą funkcji, która czekała. Gdy pierwszy zadziała zewnętrzny, zostaje tylko ogólna strona 504 bez śladu w logach WordPressa.
Jak odczytać stronę statusu PHP-FPM
Najszybszy dowód, czy 504 to kolejka, czy pojedyncze wolne żądanie, daje strona statusu PHP-FPM. Włącza ją opcja pm.status_path w konfiguracji puli, która domyślnie nie jest ustawiona. Dokumentacja PHP ostrzega, że strona ujawnia adresy żądań i informacje o zasobach, więc trzeba ją ograniczyć do żądań lokalnych albo znanych adresów IP. Parametr ?json zwraca dane w JSON, a ?full dodaje szczegóły każdego procesu.
| Pole | Co znaczy |
|---|---|
listen queue | żądania, które teraz czekają na wolny proces |
max listen queue | największa kolejka od startu puli |
active processes / idle processes | procesy zajęte i wolne |
max children reached | 1 lub więcej, jeśli pula choć raz uderzyła w pm.max_children |
slow requests | żądania, które przekroczyły request_slowlog_timeout |
Odczyt w czasie awarii jest prosty. Kolejka większa od zera i brak wolnych procesów oznaczają pełną pulę: za mało workerów albo za wolne żądania, które je trzymają. Pusta kolejka i wolne procesy przy jednoczesnym 504 oznaczają, że czas ucieka w samym żądaniu, czyli w bazie, cache albo zewnętrznym API. Górną granicę kolejki wyznacza listen.backlog, domyślnie 511 na Linuksie, zgodnie z opisem konfiguracji FPM.
Jak naprawić 504 krok po kroku
- Ustal zakres: cała strona, jeden adres czy tylko wp-admin.
- Przeczytaj logi serwera i PHP-FPM z godziny awarii.
- Włącz
debug.logi odtwórz błąd. - Wyłącz wtyczki (przez WP-CLI albo zmianą nazwy katalogu), potem włączaj po jednej i mierz czas odpowiedzi.
- Jeśli istnieje
object-cache.php, wyłącz go na próbę. - Sprawdź autoloadowane opcje i zaległe zadania WP-Cron.
- Dopiero na końcu rozważ zwiększenie puli albo timeoutów, razem z administratorem hostingu.
Jeśli 504 pojawił się zaraz po aktualizacji, zajrzyj też do poradnika o odzyskiwaniu WordPressa po nieudanej aktualizacji.
Kiedy to robota dla specjalisty
Gdy logi wskazują na pulę PHP-FPM, ale hosting nie daje dostępu do jej konfiguracji. Gdy 504 wraca po każdej naprawie. Gdy sklep traci zamówienia w czasie awarii. Przy audycie, który ma oddzielić koszt hostingu od kosztu kodu, pomaga optymalizacja wydajności strony WordPress. Gdy strona leży teraz, a przyczyna jest nieznana, ratunkiem jest naprawa i wsparcie techniczne WordPressa.






