Skip to content
EN
← Все статьи

Ошибка 504 Gateway Time-out: что значит и как исправить в nginx

Серверная стойка с прокси и бэкендами, соединёнными патч-кордами

Ошибка 504 (504 Gateway Time-out) означает, что промежуточный сервер — nginx, балансировщик или CDN — не дождался ответа от сервера приложения за отведённое время и прекратил ожидание. Сайт при этом обычно жив, но отвечает слишком медленно. Посетителю стоит обновить страницу через минуту, владельцу — искать медленный запрос в логах.

В отличие от 502 (upstream ответил невалидно или оборвал соединение), 504 — это ожидание, которое истекло. Ниже: перевод и смысл кода, что делать посетителю, где искать причину в логах nginx, Apache и PHP-FPM, как правильно настроить таймауты и как оптимизировать медленные запросы, вместо того чтобы просто прятать их за увеличенным таймаутом.

Что значит код 504 и как переводится Gateway Time-out

Согласно RFC 9110 §15.6.5, код 504 означает, что сервер, действуя как шлюз (gateway) или прокси, не получил своевременный ответ от вышестоящего сервера (upstream), к которому обратился, чтобы выполнить запрос. Ключевое слово — «своевременный»: сколько ждать, решает не стандарт, а таймаут в конфигурации прокси.

Цепочка обычно выглядит так: браузер → CDN или балансировщик → nginx → PHP-FPM, Node.js, Python или Java-приложение → база данных и внешние API. Код 504 выдаёт то звено, у которого кончилось терпение, а виновато, как правило, звено дальше по цепочке. Поэтому страница с надписью «nginx» под заголовком ещё не значит, что проблема в nginx — он лишь сообщил, что приложение за ним не ответило вовремя.

Перевод Gateway Time-out

Gateway Time-out дословно переводится как «тайм-аут шлюза», по смыслу — «шлюз не дождался ответа». Шлюзом здесь называют любой сервер-посредник, который принимает запрос от браузера и передаёт его дальше. Поэтому в русскоязычных сообщениях эту ошибку называют ещё «ошибка шлюза 504» или «504 тайм-аут шлюза». Написание Time-out через дефис встречается на стандартной странице nginx, Timeout слитно — в тексте RFC и в большинстве фреймворков; это один и тот же код.

Как выглядит ошибка на экране

Текст на экранеКто его показываетКомментарий
504 Gateway Time-out и строка nginx внизуnginx перед приложениемСамый частый вариант на VPS и хостингах
Gateway Timeout / The gateway did not receive a timely response from the upstream server or applicationApache с mod_proxyИстёк ProxyTimeout или Timeout
HTTP Error 504, HTTP 504Браузер, клиентская библиотека, мобильное приложениеКод пришёл от сервера, браузер лишь его отобразил
Error 524: A timeout occurredCloudflareЭто не 504: Cloudflare так сообщает о собственном таймауте ожидания origin
502.3 - Bad Gateway: The operation timed outIIS с модулем ARRТаймаут прокси в IIS оформлен как 502.3, а не 504

Если код 504 выдаёт бортовой компьютер автомобиля или игровой клиент — это другие ошибки с совпадающим номером, к HTTP-статусу сайта они отношения не имеют.

Ошибка 504 на сайте: что делать посетителю

Исправить 504 со стороны браузера нельзя — ошибка возникает между серверами сайта. Но можно быстро понять, у кого проблема.

  1. Подождите минуту и обновите страницу (F5, на macOS — Cmd+R). Часто 504 — следствие кратковременного всплеска нагрузки.
  2. Не отправляйте форму повторно вслепую. Если 504 появилась после оплаты или оформления заказа, запрос мог быть выполнен — прокси просто не дождался ответа. Сначала проверьте почту или личный кабинет.
  3. Откройте другой сайт. Если 504 везде, ошибку отдаёт прокси-сервер между вами и интернетом: корпоративный прокси, фильтр антивируса или роутер провайдера. Проверьте настройки прокси в системе: Windows — «Параметры → Сеть и Интернет → Прокси-сервер», macOS — «Системные настройки → Сеть → Подробнее → Прокси».
  4. Проверьте сайт снаружи через проверку HTTP-заголовков Enterno.io: если внешний запрос тоже получает 504 или долго висит, проблема на стороне сайта, а не у вас.
  5. Сообщите владельцу сайта — время, адрес страницы и действие, после которого появилась ошибка. Это сильно сокращает поиск в логах.

Очистка кэша браузера и cookies при 504 почти никогда не помогает: браузер не участвует в ожидании между прокси и приложением.

Почему сайт выдаёт 504: 7 частых причин

  1. Медленный SQL-запрос без индекса или транзакция, ждущая блокировку.
  2. Медленный внешний API — платёжный шлюз, склад, CRM, от которого зависит ответ страницы.
  3. Неоптимальный код — N+1 query, не-батчированные операции, обход больших массивов в цикле.
  4. Ресурсоёмкие задачи в request/response цикле (генерация PDF, импорт каталога, отправка email).
  5. Все воркеры заняты. У PHP-FPM закончился pm.max_children или у приложения исчерпан пул соединений к БД: новые запросы стоят в очереди, и прокси не дожидается даже начала обработки.
  6. Низкий timeout в nginx/Cloudflare для реально долгих операций (выгрузки, отчёты).
  7. Upstream недоступен по сети или заблокирован — deadlock в БД, зависший поток, упавший контейнер, файрвол молча отбрасывает пакеты к бэкенду.

Первые четыре причины — это медленный код, пятая — нехватка мощности, шестая — неверная настройка, седьмая — авария. Лечатся они по-разному, поэтому сначала диагностика, потом правка конфигов.

504 Gateway Time-out в nginx: где искать причину

nginx записывает каждый таймаут в error.log с указанием этапа, на котором кончилось ожидание. По этому тексту видно, куда смотреть дальше:

# Последние таймауты upstream
grep "upstream timed out" /var/log/nginx/error.log | tail -20

# Пример строк:
# upstream timed out (110: Connection timed out) while reading response header from upstream
# upstream timed out (110: Connection timed out) while connecting to upstream
Фраза в error.logЧто произошлоКакая директива сработала
while connecting to upstreamБэкенд не принял соединение: остановлен, перегружен, недоступен по сетиproxy_connect_timeout / fastcgi_connect_timeout
while reading response header from upstreamСоединение есть, но приложение не начало отвечать — медленный код, запрос к БД или внешнему APIproxy_read_timeout / fastcgi_read_timeout
while reading upstreamОтвет начал приходить, но между порциями данных возникла пауза длиннее таймаутаproxy_read_timeout / fastcgi_read_timeout
while sending request to upstreamnginx не смог передать тело запроса бэкенду, например большой uploadproxy_send_timeout / fastcgi_send_timeout

Важно: proxy_read_timeout — это не лимит на весь ответ, а максимальная пауза между двумя операциями чтения. По умолчанию для proxy_* и fastcgi_* это 60 секунд. Подробнее о том, где лежат журналы и как их читать, — в статье про логи nginx.

Какие запросы медленные: время ответа в access.log

Стандартный формат combined не пишет время выполнения запроса, поэтому сначала добавьте его в лог, а затем отфильтруйте долгие запросы:

# /etc/nginx/nginx.conf, блок http
log_format timing '$remote_addr [$time_local] "$request" $status '
                  '$request_time $upstream_response_time';
access_log /var/log/nginx/timing.log timing;

# Проверить и применить
nginx -t && systemctl reload nginx

# Запросы, где upstream отвечал дольше 5 секунд
awk '$NF+0 > 5' /var/log/nginx/timing.log | tail -20

# Какие URL чаще всего получают 504
awk '$7 == 504 {print $5}' /var/log/nginx/timing.log | sort | uniq -c | sort -rn | head

Так вы увидите не «сайт тормозит», а конкретные адреса: например, /export или поиск по каталогу. Именно их и нужно оптимизировать.

Проверка в обход nginx

Чтобы понять, медленное ли само приложение, отправьте запрос напрямую на бэкенд с сервера и замерьте время:

# Linux/macOS: время до первого байта и общее время
curl -o /dev/null -s -w 'code=%{http_code} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://example.ru/export

# Напрямую к приложению на порту 8080, минуя nginx
curl -o /dev/null -s -w '%{http_code} %{time_total}\n' -H 'Host: example.ru' http://127.0.0.1:8080/export

# Windows PowerShell (curl.exe есть в Windows 10 и новее)
curl.exe -o NUL -s -w "code=%{http_code} total=%{time_total}\n" https://example.ru/export

Если напрямую запрос выполняется 90 секунд, а таймаут nginx — 60, причина найдена: медленное приложение, а не прокси.

Диагностика медленных запросов в БД и PHP

# MySQL slow log
mysqldumpslow -t 10 /var/log/mysql/slow.log

# PHP-FPM slow log
# /etc/php/8.4/fpm/pool.d/www.conf:
# slowlog = /var/log/php/www-slow.log
# request_slowlog_timeout = 5s
tail -100 /var/log/php/www-slow.log

# Закончились ли воркеры PHP-FPM
grep "max_children" /var/log/php8.4-fpm.log
# WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

# Node.js: event loop lag
// npm install clinic
// clinic doctor -- node app.js

Slow log PHP-FPM особенно полезен: для каждого запроса дольше request_slowlog_timeout он записывает стек вызовов, и видно, на какой функции скрипт стоял — на PDOStatement->execute(), curl_exec() или в собственном цикле. Путь к основному логу PHP-FPM зависит от дистрибутива, его задаёт директива error_log в php-fpm.conf.

Проверьте внешнее время ответа через PageSpeed Check от Enterno.io — получите TTFB, метрики Web Vitals и узкие места.

Как исправить ошибку 504: правильная настройка timeout в nginx

http {
    # Соединение с upstream
    proxy_connect_timeout 10s;

    # Отправка запроса upstream'у
    proxy_send_timeout 30s;

    # Чтение ответа от upstream
    proxy_read_timeout 60s;

    # Для FastCGI (PHP-FPM)
    fastcgi_connect_timeout 10s;
    fastcgi_send_timeout 30s;
    fastcgi_read_timeout 60s;
}

# Long-polling эндпоинт — отдельный location
location /api/long-poll {
    proxy_read_timeout 300s;  # 5 минут
    proxy_pass http://backend;
}

Несколько правил, которые избавляют от повторных 504:

  • Увеличивайте таймаут точечно — в location долгого эндпоинта, а не на весь сайт. Глобальные 300 секунд превращают каждый зависший запрос в занятый на 5 минут воркер.
  • Для PHP-FPM нужна директива fastcgi_read_timeout, а не proxy_read_timeout: если сайт работает через fastcgi_pass, proxy_* на него не действуют. Это самая частая причина, почему «увеличил таймаут, а 504 осталась».
  • proxy_connect_timeout держите коротким. По документации nginx он обычно не может превышать 75 секунд, а долгое ожидание соединения лишь маскирует упавший бэкенд.
  • Учитывайте повторы. По умолчанию proxy_next_upstream error timeout: при нескольких серверах в upstream nginx после таймаута отправит запрос на следующий, и пользователь прождёт дольше одного таймаута. Неидемпотентные запросы (POST) nginx по умолчанию на другой сервер не повторяет.
  • Цепочка таймаутов должна сужаться к клиенту: таймаут приложения меньше таймаута nginx, таймаут nginx меньше таймаута CDN или балансировщика. Тогда ошибку сформирует ближайшее к причине звено, и в логах будет видно, что произошло.

После правки — nginx -t и systemctl reload nginx. Описание всех директив — в документации модуля ngx_http_proxy_module. На виртуальном хостинге доступа к конфигу nginx обычно нет — таймаут меняет поддержка хостинга, а в панели управления, как правило, можно изменить только параметры PHP.

Apache: ProxyTimeout

# Глобально для mod_proxy (если не задан — берётся Timeout, по умолчанию 60 секунд)
ProxyTimeout 120

# Или только для конкретного бэкенда
ProxyPass "/export/" "http://127.0.0.1:8080/export/" timeout=300

# Проверка и перезапуск
apachectl configtest && systemctl reload apache2

В журнале ошибок Apache таймаут прокси обычно сопровождается строкой (70007)The timeout specified has expired.

PHP-FPM: max_execution_time

# php.ini
max_execution_time = 30
max_input_time = 60

# Для экспорта больших данных:
# Установите per-request через ini_set()
ini_set('max_execution_time', 300);  # 5 минут
set_time_limit(300);

# Но лучше вынести в очередь!

Два нюанса. Во-первых, на Linux max_execution_time не учитывает время, проведённое вне скрипта — в запросах к БД, сетевых вызовах, sleep() (документация PHP). Скрипт может ждать ответа внешнего API пять минут, не нарушив лимит в 30 секунд, — и nginx отдаст 504 раньше. Во-вторых, жёсткий предел на стороне пула задаёт request_terminate_timeout в pool.d/www.conf: когда он срабатывает, воркер убивается, и nginx обычно получает оборванное соединение — то есть 502, а не 504. Держите его чуть больше fastcgi_read_timeout, чтобы ошибки были однозначными.

Node.js: server timeout

const server = app.listen(3000);
server.setTimeout(60000);  // 60 секунд
server.keepAliveTimeout = 61000;
server.headersTimeout = 65000;  // должен быть > keepAliveTimeout

// Для Fastify
const app = Fastify({
  connectionTimeout: 60000,
  keepAliveTimeout: 61000,
});

keepAliveTimeout приложения держите больше, чем keepalive-таймаут прокси или балансировщика перед ним: иначе Node закроет простаивающее соединение в тот момент, когда прокси пошлёт в него новый запрос, и это даст эпизодические 502.

Правильное решение: вынос в background

Увеличивать timeout до бесконечности — антипаттерн. Правильное решение — вынести долгие операции в очередь.

// Плохо: блокируем request
app.post('/generate-report', async (req, res) => {
  const pdf = await generateBigPDF(req.body);  // 3 минуты
  await sendEmail(pdf);
  res.json({ok: true});
});

// Хорошо: очередь + уведомление
app.post('/generate-report', async (req, res) => {
  const jobId = await queue.add('generate-report', req.body);
  res.status(202).json({jobId, status: 'queued'});
});

// Worker обрабатывает в фоне
queue.process('generate-report', async (job) => {
  const pdf = await generateBigPDF(job.data);
  await sendEmail(pdf);
});

Клиент получает 202 Accepted + jobId, опрашивает статус через /jobs/:id или получает уведомление через WebSocket/webhook.

Оптимизация медленных запросов БД

-- Ищите long queries
SHOW PROCESSLIST;
SHOW FULL PROCESSLIST;

-- EXPLAIN плана запроса
EXPLAIN SELECT * FROM orders WHERE user_id = 1 ORDER BY created_at DESC LIMIT 10;

-- Добавьте индекс если нужен
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC);

-- Проверьте размеры таблиц
SELECT table_name, ROUND(data_length/1024/1024) AS mb
FROM information_schema.tables
WHERE table_schema = 'your_db'
ORDER BY data_length DESC LIMIT 10;

Если в SHOW FULL PROCESSLIST много запросов в состоянии ожидания блокировки, проблема не в индексе, а в долгой транзакции, которая держит строки: найдите её и сократите.

504 и Cloudflare 524: в чём разница

Cloudflare ждёт ответа от вашего сервера по умолчанию 100 секунд. Когда время выходит, он возвращает не 504, а собственный код 524 A timeout occurred. Если же посетитель видит 504 на сайте за Cloudflare, чаще всего её сформировал ваш nginx или балансировщик, а Cloudflare лишь передал ответ дальше, — ищите причину в логах origin. Разбор 524 и соседних кодов — в статье про ошибки Cloudflare 520, 521 и 524. Варианты для реально долгих запросов:

  • Использовать Enterprise plan (до 6000 сек).
  • Перевести долгие эндпоинты на Origin bypass через отдельный поддомен без CF proxy.
  • Оптимизировать код до <100 сек (правильный подход).

Чем отличаются ошибки 502, 503, 504 и 524

КодНазваниеЧто произошлоС чего начать
502Bad GatewayUpstream ответил невалидно, оборвал соединение или не запущен (connection refused)Запущен ли PHP-FPM или приложение, совпадает ли сокет или порт
503Service UnavailableСервер сознательно не обслуживает запрос: перегрузка, лимит, режим обслуживанияЛимиты запросов, maintenance-режим, заголовок Retry-After
504Gateway TimeoutПрокси не дождался ответа upstream за отведённое времяError.log прокси, slow log приложения и БД, таймауты в цепочке
524A timeout occurred (Cloudflare)Cloudflare установил соединение с origin, но не получил ответ вовремяДолгие запросы на origin, вынос тяжёлых операций в фон

Подробные разборы соседних кодов: 502 Bad Gateway и 503 Service Unavailable. Полный справочник статусов — в статье про коды ответа сервера.

Похожая ситуация бывает в 1С: при работе через веб-клиент, опубликованный на Apache или IIS, 504 появляется, когда длительная операция не укладывается в таймаут веб-сервера или прокси перед ним. Лечится так же — таймаутом для конкретной публикации или переносом операции в фоновое задание.

Как проверить сайт на 504

  • Проверка HTTP-заголовков — покажет код ответа и время ответа сайта снаружи, из другой сети. Если внешний запрос висит десятки секунд, 504 вызвана медленным приложением.
  • Traceroute — пригодится, если 504 выдаёт ваш балансировщик или CDN, а бэкенд расположен в другом дата-центре: покажет, доходят ли пакеты до сервера и где растут задержки.
  • PageSpeed Check — время до первого байта (TTFB): если оно стабильно близко к таймауту прокси, 504 будут повторяться при любом всплеске нагрузки.

Итог

504 — не баг timeout'а, а симптом медленного кода, нехватки воркеров или внешнего API. Порядок действий: найти в error.log этап, на котором кончилось ожидание, по access.log определить медленные URL, по slow log — конкретную функцию или запрос. Мониторьте slow log, оптимизируйте запросы, выносите долгие задачи в очередь. Timeout'ы настраивайте с запасом, но не бесконечно. Подключите Enterno.io для автоматической фиксации 504 по регионам.

Частые вопросы

Чем 504 отличается от 502?

504 — upstream не ответил в срок. 502 — upstream ответил невалидно, закрыл соединение или вообще не запущен.

Какой timeout адекватен?

Web-запросы: 30–60 сек. API: 10–30 сек. Long-polling: 300+ сек. Долгие задачи: выносим в очередь.

Я увеличил proxy_read_timeout, а 504 осталась. Почему?

Сайт на PHP-FPM работает через fastcgi_pass, и на него действует fastcgi_read_timeout. Кроме того, перед nginx может стоять CDN или балансировщик со своим, более коротким таймаутом, — проверьте всю цепочку.

Можно ли исправить ошибку 504 на стороне пользователя?

Нет. Можно лишь подождать и обновить страницу, а если 504 показывают все сайты подряд — проверить системный или корпоративный прокси.

Как поймать 504 автоматически?

Enterno.io Monitors с коротким timeout триггерят алерт. Также встройте APM (Sentry, New Relic).

Влияет ли 504 на SEO?

Да. Если робот Яндекса или Google регулярно получает 5xx, он снижает частоту обхода, а страницы, долго отвечающие ошибкой, со временем выпадают из индекса. Единичные 504 на пару минут опасности не несут.

Проверьте ваш сайт прямо сейчас

Проверить HTTP-статус сайта →
Другие статьи: HTTP
HTTP
HTTP-заголовки: полный разбор запроса и ответа сервера
10.03.2025 · 1 724 просм.
HTTP
Жизненный цикл HTTP-запроса: от URL до готовой страницы
16.03.2026 · 1 246 просм.
HTTP
Ошибка 400 Bad Request: что значит код и как исправить
13.07.2026 · 1 144 просм.
HTTP
HTTP-методы: GET, POST, PUT, DELETE и другие
16.03.2026 · 1 071 просм.