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

504 Gateway Timeout: причины и решения для админов

Ошибка 504 Gateway Timeout возникает, когда прокси (nginx, Cloudflare) ждал ответ от upstream дольше, чем разрешено timeout'ом. В отличие от 502 (невалидный ответ), 504 — это ожидание, которое истекло. Разберём причины, как настроить timeout'ы правильно и как оптимизировать медленные запросы, вместо того чтобы просто их скрывать.

Что означает 504

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

6 частых причин 504

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

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

# Top медленных запросов в access.log
awk '$10 > 5' /var/log/nginx/access.log | head -20

# 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

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

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

Правильная настройка 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;
}

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);

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

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,
});

Правильное решение: вынос в 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;

Cloudflare 504 — специфика

Cloudflare имеет жёсткий лимит 100 секунд на free/pro плане. Варианты:

Часто задаваемые вопросы (FAQ)

В: Чем 504 отличается от 502?
О: 504 — upstream не ответил в срок. 502 — upstream ответил невалидно или закрыл connection.

В: Какой timeout адекватен?
О: Web-запросы: 30-60 сек. API: 10-30 сек. Long-polling: 300+ сек. Долгие задачи: выносим в очередь.

В: Как поймать 504 автоматически?
О: Enterno.io Monitors с коротким timeout триггерят алерт. Также встройте APM (Sentry, New Relic).

В: Влияет ли 504 на SEO?
О: Да, критично. Googlebot имеет свой timeout (~30 сек). Систематические 504 ведут к деиндексации.

Заключение

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

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

Проверить →
Другие статьи: HTTP
HTTP
Server-Sent Events vs WebSockets: выбор технологии реального времени
16.03.2026 · 34 просм.
HTTP
HTTP заголовки: полное руководство
10.03.2025 · 76 просм.
HTTP
502 Bad Gateway: что значит и как починить
15.04.2026 · 7 просм.
HTTP
Cache-Control заголовки: полный гид по кэшированию
15.04.2026 · 6 просм.