Błąd 504 Gateway Timeout oznacza, że serwer działający jako brama lub proxy czekał na odpowiedź od serwera za nim i w końcu zrezygnował. Żądanie dotarło do Twojego CDN, load balancera albo serwera WWW, zostało przekazane do aplikacji, a aplikacja nie odpowiedziała przed upływem limitu czasu.
Serwer za proxy często nadal działa. Jest po prostu zbyt wolny – albo wolne jest coś, na co on sam czeka. To odróżnia 504 od większości awarii: restart rzadko pomaga na dłużej. Z tego poradnika dowiesz się, jak ustalić, który limit czasu zadziałał, co zwykle spowalnia żądanie i jak usunąć przyczynę, a nie tylko objaw.
Co mówi Ci błąd 504
Żądanie do nowoczesnej strony przechodzi przez kilka warstw, a każda z nich ma własny limit czasu oczekiwania na kolejną:
CDN, taki jak Cloudflare, czeka na Twój serwer źródłowy przez stały czas.
Load balancer ma limit bezczynności lub czasu odpowiedzi dla każdego celu.
nginx czeka na upstream zgodnie z proxy_read_timeout lub fastcgi_read_timeout, domyślnie 60 sekund.
Aplikacja ma własne limity, np. max_execution_time w PHP albo timeout workera w Gunicornie.
Błąd 504 zwraca pierwsza warstwa, której skończy się limit. Sąsiednie kody oznaczają co innego: 502 Bad Gateway to sytuacja, w której upstream odpowiedział czymś nieprawidłowym albo wcale, a 503 Service Unavailable oznacza, że usługa odrzuciła żądanie, bo jest przeciążona lub trwa przerwa serwisowa.
Ustal, który limit czasu zadziałał
Zmierz czas żądania. Błąd 504, który zawsze pojawia się po tej samej liczbie sekund, wskazuje na jeden konkretny limit:
curl -s -o /dev/null -w „status %{http_code} after %{time_total}s\n” https://www.example.com/reports
status 504 after 60.04s
Następnie sprawdź nagłówki odpowiedzi i stronę błędu, aby zobaczyć, która warstwa odpowiedziała – tak jak przy każdym błędzie 5xx. Prosta strona nginx z server: nginx oznacza, że limit przekroczył Twój własny serwer WWW. Strona z logo CDN, na której widnieje nazwa Twojego hosta, oznacza, że CDN nie doczekał się odpowiedzi serwera źródłowego.
nginx zapisuje przekroczenie limitu w logu razem z adresem, na który czekał:
upstream timed out (110: Connection timed out) while reading response header from upstream,
upstream: „fastcgi://unix:/run/php/php8.3-fpm.sock”, request: „GET /reports HTTP/2.0”
Wiesz już, która strona jest wolna i która część stosu kazała jej czekać. Teraz trzeba ustalić dlaczego.
Najczęstsze przyczyny i jak je usunąć
Wolne zapytania do bazy danych
To najczęstsza przyczyna. Zapytanie, które przy tysiącu wierszy trwało 50 milisekund, przy milionie trwa 40 sekund, bo przeszukuje całą tabelę. Włącz log wolnych zapytań i znajdź zapytania danej strony:
# MySQL / MariaDB
SET GLOBAL slow_query_log = 'ON’;
SET GLOBAL long_query_time = 1;
# PostgreSQL, in postgresql.conf
log_min_duration_statement = 1000
Uruchom najwolniejsze zapytanie z EXPLAIN i szukaj pełnych skanów tabel. Zwykle wystarczy dodać brakujący indeks. Drugim typowym podejrzanym są blokady: długa transakcja albo migracja może trzymać tabelę, podczas gdy każde żądanie, które jej potrzebuje, czeka.
Wolne zewnętrzne API
Strony podczas generowania często wywołują inne usługi: operatora płatności, kalkulator wysyłki, wyszukiwarkę, CRM. Jeśli taka usługa jest wolna, Twoja strona też jest wolna, a proxy przekracza limit czasu. Ustaw krótki timeout dla każdego wywołania wychodzącego – kilka sekund zamiast domyślnej wartości biblioteki – i zdecyduj, co strona pokaże, gdy wywołanie się nie uda. Szacunkowy koszt wysyłki z dopiskiem „obliczany przy kasie” jest lepszy niż 504.
Pilnuj usług, od których zależysz. Monitorowanie usług zewnętrznych w Uptimecheck śledzi strony statusu 31 usług, takich jak Klarna, Shopify i Cloudflare, więc wolny dostawca pojawia się obok Twoich własnych sprawdzeń.
Za mało workerów na ruch
Gdy wszystkie workery są zajęte, nowe żądania czekają w kolejce. Same nie są wolne – czekają na swoją kolej, a zegar proxy przez cały ten czas tyka. PHP-FPM informuje o tym w logu komunikatem server reached pm.max_children. Więcej workerów pomoże tylko wtedy, gdy serwer ma dla nich pamięć i CPU. Często lepiej skrócić każde żądanie, aby te same workery obsłużyły ich więcej, i cache’ować strony, które nie zmieniają się w zależności od odwiedzającego.
Długie zadania w żądaniu HTTP
Eksporty, importy, generowanie raportów, przetwarzanie obrazów czy wysyłka setek e-maili nie powinny odbywać się w żądaniu HTTP. Trwają tyle, ile trwają, i prędzej czy później któreś z nich przekroczy limit czasu. Przenieś je do kolejki zadań w tle: żądanie uruchamia zadanie i od razu zwraca odpowiedź, a strona odpytuje o wynik albo użytkownik dostaje e-mail, gdy wszystko jest gotowe.
Przeciążony serwer
Wysokie obciążenie CPU, brak pamięci spychający serwer do swapu albo dysk, który nie nadąża, spowalniają wszystko naraz. Na to wskazuje 504 na każdej stronie, a nie tylko na jednej. Sprawdź CPU, pamięć, swap i oczekiwanie na dysk w tym samym okresie:
uptime
free -m
iostat -x 5 3
Monitorowanie serwerów przechowuje tę historię, więc widzisz, co serwer robił w minucie, w której zaczęły się błędy 504, zamiast zgadywać po fakcie.
Problemy sieciowe między warstwami
Jeśli proxy w ogóle nie może połączyć się z upstreamem, np. dlatego, że firewall po cichu porzuca pakiety, zamiast odpowiadać odmową, połączenie wisi aż do przekroczenia limitu. Kończy się to błędem 504, a nie 502. Sprawdź, czy z tej samej maszyny proxy da się otworzyć połączenie z adresem i portem upstreamu.
Kiedy warto podnieść limit czasu
Czasem żądanie słusznie trwa długo: duży upload, raport, który administrator pobiera raz w miesiącu. Wtedy podnieś limit tylko dla tej ścieżki i zachowaj kolejność warstw, tak aby zewnętrzne czekały dłużej niż wewnętrzne:
location /admin/exports/ {
proxy_read_timeout 300s;
proxy_pass http://app;
}
Podniesienie limitu dla całej strony nie naprawi wolnych podstron. Odwiedzający dłużej czekają, zanim zobaczą błąd, a wolne żądania dłużej blokują workery, co wydłuża kolejkę dla wszystkich pozostałych.
Jak monitorowanie wyłapuje błędy 504
Błąd 504 rzadko pojawia się znikąd. Strona z tygodnia na tydzień zwalniała, w miarę jak rosły dane, aż pewnego dnia przekroczyła limit. To dobra wiadomość, bo oznacza, że można to zobaczyć z wyprzedzeniem.
Obserwuj czas odpowiedzi, nie tylko status. Uptimecheck zapisuje czas odpowiedzi każdego sprawdzenia w podziale na DNS, połączenie, TLS, serwer i pobieranie, więc widzisz, czy zwolnił serwer, czy sieć. Alert o wolnej odpowiedzi informuje, gdy strona przekroczy ustawiony przez Ciebie próg – na długo przed limitem czasu proxy. Nasz poradnik o tym, jaki czas odpowiedzi jest dobry, pomoże Ci wybrać próg.
Potwierdzaj awarie przed wysłaniem alertu. Sprawdzenia mogą działać nawet co minutę ze Sztokholmu, Londynu i Nowego Jorku, a każda awaria jest potwierdzana z drugiej lokalizacji, więc jedno wolne żądanie nikogo nie budzi.
Monitoruj bezpośrednio wolne strony. Wyszukiwarka, koszyk, strony konta i raporty to miejsca, gdzie pojawiają się błędy 504 – rzadko jest to strona główna. Dodaj dla nich monitory dostępności z limitem czasu odpowiadającym temu, ile odwiedzający jest w stanie czekać.
Checklista dla błędu 504
Zmierz czas żądania: okrągła liczba sekund wskazuje, który limit zadziałał.
Przeczytaj nagłówki i stronę błędu, aby ustalić, która warstwa przekroczyła limit.
Znajdź wolną stronę w logu błędów proxy.
Poszukaj wolnych zapytań, blokad i wolnych wywołań zewnętrznych dla tej strony.
Sprawdź workery, CPU, pamięć, swap i dysk w tych samych minutach.
Przyspiesz wolny element, dodaj cache albo przenieś go do zadania w tle.
Podnoś limity tylko dla ścieżek, które słusznie trwają długo – zewnętrzne warstwy dłużej niż wewnętrzne.
Ustaw alerty o wolnych odpowiedziach, aby kolejny 504 zauważyć, gdy jest jeszcze tylko spowolnieniem.