TTFB расшифровывается как Time to First Byte — время от момента, когда браузер отправил запрос, до момента, когда получил первый байт ответа. Звучит как узкая техническая метрика, но на деле это один из самых важных показателей производительности сайта.

Google включил TTFB в сигналы Core Web Vitals (через метрику LCP), и если он у вас выше 800 мс — это уже проблема. Хорошим считается TTFB до 200 мс. Всё, что между — зона, где можно и нужно работать.

Что вообще происходит за это время

Пока браузер ждёт первый байт, сервер успевает сделать кучу всего: получить запрос, разобрать маршрут, сходить в базу данных, выполнить бизнес-логику, сформировать HTML и отправить ответ. Плюс к этому — сетевые задержки: DNS-резолвинг, TCP-соединение, TLS-хендшейк.

Примерно так выглядит типичный «путь» запроса:

  1. DNS lookup — 20–120 мс (зависит от провайдера и кэша)
  2. TCP connection — 10–100 мс
  3. TLS handshake — 30–100 мс
  4. Время обработки на сервере — от 10 мс до нескольких секунд
  5. Сеть (передача первого байта) — зависит от расстояния до сервера

Если складывать всё это, легко получить 500–700 мс ещё до того, как сервер вообще начал что-то считать. Поэтому оптимизация TTFB — это работа сразу на нескольких уровнях.

Серверная сторона: где теряется больше всего

Кэширование — самый быстрый способ ускорить ответ

Если сервер каждый раз пересчитывает одно и то же — вы платите за это временем. Простой пример: главная страница интернет-магазина. Список категорий, баннер, рекомендации — это данные, которые меняются раз в несколько часов. Зачем каждый раз ходить в базу?

Решение: кэшировать HTML-ответ целиком или отдельные блоки. Для этого используют Redis или Memcached. Настраивается через промежуточный слой в приложении или прямо в Nginx.

Пример конфига Nginx для кэширования ответов:

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;

server {
    location / {
        fastcgi_cache my_cache;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_use_stale error timeout updating;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

Заголовок X-Cache-Status показывает в ответе — HIT (отдано из кэша) или MISS (пришлось считать). Полезно при отладке.

База данных — частый виновник медленного TTFB

Типичная история: сайт работал нормально, добавили несколько тысяч товаров — и TTFB вырос в три раза. Причина — запросы к базе без индексов.

Что делать:

  • Добавить индексы на поля, по которым фильтруете (WHERE, ORDER BY, JOIN)
  • Убрать N+1 запросы — это когда вместо одного запроса с JOIN делают сотню мелких в цикле
  • Настроить connection pool — чтобы не открывать новое соединение с базой на каждый запрос
  • Вынести тяжёлые аналитические запросы в фоновые задачи

Проверить медленные запросы можно через EXPLAIN ANALYZE в PostgreSQL или SHOW PROCESSLIST в MySQL.

PHP-сайты: OPcache обязателен

Если у вас сайт на PHP и OPcache не включён — вы теряете 30–70% производительности просто так. OPcache компилирует PHP-файлы в байткод и хранит в памяти. При каждом запросе PHP не нужно заново парсить и компилировать код.

Минимальный конфиг в php.ini:

opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60

Серверное железо и настройка

Если ваш сайт живёт на shared-хостинге и TTFB стабильно выше 600 мс — это часто не ваш код виноват, а соседи по серверу, которые жрут ресурсы. Переход на VPS с выделенными ресурсами решает это.

На VPS важно:

  • Выбрать нужное количество воркеров для PHP-FPM или Gunicorn (обычно = количеству CPU)
  • Включить keepalive-соединения в Nginx
  • Настроить gzip или brotli для сжатия ответов
gzip on;
gzip_comp_level 5;
gzip_types text/plain text/css application/json application/javascript;

CDN: как расстояние убивает TTFB и что с этим делать

Скорость света — это не просто физика, это реальное ограничение. Запрос от пользователя во Владивостоке до сервера в Москве туда-обратно занимает минимум 80–100 мс только на сеть, без учёта обработки. Это называется латентность.

CDN (Content Delivery Network) — сеть серверов, распределённых географически. Пользователь получает ответ от ближайшего узла, а не от основного сервера.

Что кэшировать на CDN

CDN лучше всего подходит для статики: картинки, CSS, JS, шрифты, PDF. Это контент, который не меняется от пользователя к пользователю.

Динамические страницы кэшировать на CDN сложнее, но возможно — если правильно настроить правила. Например, для незалогиненных пользователей страница каталога одинакова для всех. Её можно отдавать с CDN с TTL в 5 минут.

Популярные CDN-провайдеры: Cloudflare (есть бесплатный тариф), BunnyCDN (дешевле, хорошие точки в СНГ), AWS CloudFront, Fastly.

Cloudflare и TTFB

При подключении Cloudflare TTFB иногда даже немного растёт — потому что запрос теперь идёт через их прокси. Но это компенсируется другими оптимизациями: TLS termination близко к пользователю, HTTP/2 push, кэш статики.

Важный момент: у Cloudflare есть режим «Full (Strict)» для SSL — используйте именно его, иначе трафик между Cloudflare и вашим сервером идёт без шифрования.

Настройка заголовков кэша

CDN ориентируется на заголовки, которые отдаёт ваш сервер. Если Cache-Control: no-store — CDN ничего не закэширует. Правильная настройка:

# Для статики
Cache-Control: public, max-age=31536000, immutable

# Для страниц, которые меняются
Cache-Control: public, max-age=300, stale-while-revalidate=60

stale-while-revalidate — отличная директива: CDN отдаёт закэшированную версию пользователю, а фоном обновляет кэш. Пользователь не ждёт.

Приоритизация ресурсов: браузер и сервер

Даже если TTFB низкий, страница может загружаться медленно — из-за того, что браузер не знает, что важно загрузить первым.

Preconnect и dns-prefetch

Если на странице есть ресурсы с других доменов — шрифты из Google Fonts, скрипты аналитики, CDN-статика — браузер тратит время на DNS и TCP для каждого из них.

preconnect говорит браузеру: «Подключись к этому домену заранее, нам он скоро понадобится».

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>

dns-prefetch — более лёгкий вариант, только резолвит DNS без установки соединения. Используйте его для доменов, которые нужны не сразу:

<link rel="dns-prefetch" href="https://analytics.example.com">

Preload критических ресурсов

preload — инструкция браузеру загрузить конкретный ресурс с высоким приоритетом, до того, как он встретится в HTML.

<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/css/critical.css" as="style">

Особенно важно для шрифтов — без preload браузер узнает о них только после загрузки CSS, и только потом начнёт их качать. Это прямая причина мигания текста (FOUT).

Fetchpriority: явно говорим браузеру, что важно

Атрибут fetchpriority появился в 2022 и теперь поддерживается во всех современных браузерах. Позволяет повысить или понизить приоритет конкретного ресурса.

<!-- Главная картинка — высокий приоритет -->
<img src="hero.webp" fetchpriority="high" alt="Hero">

<!-- Картинки ниже экрана — пониженный приоритет -->
<img src="product-3.webp" fetchpriority="low" loading="lazy" alt="Товар">

Для LCP-изображения (то, что видно первым при загрузке) fetchpriority="high" даёт заметный прирост.

Early Hints (103)

Это относительно новый HTTP-статус. Сервер отправляет подсказки браузеру ещё до того, как сформирован основной ответ (200). Браузер сразу начинает загружать критические ресурсы.

Пример заголовка:

HTTP/1.1 103 Early Hints
Link: </css/main.css>; rel=preload; as=style
Link: </fonts/inter.woff2>; rel=preload; as=font

Early Hints поддерживает Cloudflare, Nginx начиная с версии 1.25.1. Выигрыш — 50–200 мс, особенно заметен на медленных соединениях.

Как измерить TTFB

Прежде чем что-то оптимизировать, нужно понять, что именно тормозит.

Chrome DevTools — самый простой способ. Открываем Network, кликаем на первый запрос (документ), смотрим вкладку Timing. Там будет разбивка: Queuing, Stalled, DNS Lookup, Initial Connection, SSL, Request sent, Waiting (TTFB), Content Download.

WebPageTest (webpagetest.org) — более детальный анализ. Можно выбрать локацию сервера (Москва, Санкт-Петербург), скорость соединения, посмотреть водопад загрузки.

curl — для быстрой проверки прямо из терминала:

curl -o /dev/null -s -w \
  "DNS: %{time_namelookup}\nConnect: %{time_connect}\nTLS: %{time_appconnect}\nTTFB: %{time_starttransfer}\nTotal: %{time_total}\n" \
  https://example.com

Запускайте несколько раз — первый запрос всегда медленнее из-за холодного кэша.

Что делать, если TTFB высокий, а сервер мощный

Иногда железо не при чём. Проверьте:

  • Медленные сторонние скрипты — скрипты аналитики, чат-виджеты, пиксели соцсетей. Они грузятся параллельно, но могут блокировать рендер. Грузите их с async или defer.
  • Синхронные запросы к внешним API — если ваш сервер при формировании страницы ждёт ответа от стороннего сервиса (курс валюты, данные о погоде), и тот отвечает медленно — вы ждёте вместе с ним. Кэшируйте такие данные локально.
  • Большой размер сессии — в PHP и Python сессия часто хранится в файлах. При высокой нагрузке это медленно. Переходите на Redis.
  • Серверный рендеринг без стриминга — если вы используете Next.js или подобные фреймворки, включите Streaming. Браузер начнёт получать HTML до того, как сервер закончил считать всю страницу.

Реальный результат: что можно получить

Вот типичная картина до и после оптимизации для среднего корпоративного сайта:

Что сделали Выигрыш по TTFB
Включили OPcache −100–200 мс
Добавили кэш страниц (Redis) −200–400 мс
Подключили CDN −50–150 мс (зависит от географии)
Добавили индексы в БД −50–300 мс
Включили Early Hints −50–100 мс

Сложите всё — и из TTFB в 800 мс легко получите 200–300 мс. Это реальный уровень изменений, которых достигают при грамотной работе с производительностью.

Кстати, в REEXY при разработке корпоративных сайтов (от 15 000 ₽) и интернет-магазинов (от 10 000 ₽) настройка кэширования и базовая оптимизация TTFB входят в стандартный процесс — чтобы сайт с первого дня не тормозил.

Приоритеты: с чего начать

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

  1. Измерьте текущий TTFB через DevTools или curl
  2. Включите OPcache (если PHP) — бесплатно и быстро
  3. Настройте кэширование на уровне Nginx или добавьте Redis
  4. Проверьте медленные запросы к базе через EXPLAIN
  5. Подключите CDN (Cloudflare бесплатен для базового использования)
  6. Добавьте preconnect и preload для критических ресурсов
  7. Протестируйте Early Hints, если сервер поддерживает

TTFB — это не разовая задача, а часть культуры разработки. Сайты деградируют со временем: добавляются новые запросы к базе, скрипты аналитики, плагины. Мониторинг производительности раз в квартал позволяет поймать регрессии до того, как их заметят пользователи и поисковики.