Оптимизация на TTFB (Time to First Byte): Пълно ръководство за 2026 г.

Намалете TTFB под 200 ms през 2026 г.: измерване с curl и RUM, CDN edge кеширане на HTML, HTTP/3, Brotli и Early Hints. Готови примери от практиката.

TTFB оптимизация: Пълно ръководство 2026

Обновено: 31 май 2026 г.

TTFB (Time to First Byte) е времето от изпращането на HTTP заявка до получаването на първия байт от отговора на сървъра. Добра цел за 2026 г. е под 200 ms при p75 на полето, а всичко над 800 ms се счита за бавно според Chrome User Experience Report. TTFB е "невидимият" компонент на LCP: ако сървърът ви връща HTML за 1.2 секунди, никаква frontend магия няма да докара LCP под 2.5 s. В тази статия показвам как точно да измерите TTFB, как да го разделите на DNS, TLS, заявка и сървърна обработка, и как да го намалите с CDN, edge кеш, Brotli, HTTP/3 и Early Hints (103).

  • Целева стойност за TTFB през 2026 г.: под 200 ms на p75. Всичко над 800 ms е "слаб" по CrUX.
  • TTFB = DNS lookup + TCP/TLS handshake + изпращане на заявка + server processing + връщане на първия байт. Истинският виновник почти винаги е server processing.
  • CDN с edge кеширане на HTML свалят TTFB от 600 до 900 ms на 30 до 80 ms за кеширани отговори.
  • Early Hints (103) позволяват на браузъра да започне preload на критични ресурси, докато сървърът още генерира HTML. Реално подобрение на LCP с 100 до 300 ms.
  • HTTP/3 (QUIC) намалява handshake-а с 1 RTT и елиминира TCP head-of-line blocking, забележимо на 3G/4G мрежи.
  • Brotli компресия на ниво 4 до 6 дава 15 до 25% по-малки HTML отговори от gzip без значителен CPU overhead.

Какво е TTFB и защо има значение?

TTFB е времевият интервал между момента, в който браузърът изпраща HTTP заявка, и момента, в който получава първия байт от HTTP отговора. Това число включва всичко "невидимо" преди рендирането: DNS резолюция, TCP отваряне, TLS handshake, изпращане на заявката по мрежата, време за обработка на сървъра и обратното пътуване на първия байт. В Chrome DevTools го виждате като "Waiting for server response" в Network таба, а в PerformanceNavigationTiming се изчислява като responseStart - requestStart (или по-точно за полеви измервания: responseStart - startTime, което включва и redirect/DNS/TCP).

Защо ме интересува лично TTFB? Честно казано, имам последователно наблюдение от 2026 г.: при сайт с лош TTFB не съществува "лесен" LCP fix. Помня един случай миналата зима, когато правих trace на сесия с TTFB 900 ms, и LCP-то беше блокирано от самото начало. Браузърът просто нямаше какво да рисува.

TTFB е и единственият Web Vital сигнал, който се измерва преди да заредите каквото и да е от HTML-а. Така че проблеми тук засягат всяка следваща метрика. Той е предупредителна лампа за претоварен сървър, бавна база данни, неподходящ хостинг регион или липсваща edge стратегия.

Какъв е добрият TTFB през 2026 г.?

Според официалните насоки на web.dev, Google поддържа следните прагове за TTFB на p75 (75-ия персентил на реални потребители):

КатегорияTTFB (p75)Какво означава
Добър≤ 800 msОфициалният праг на Google. В практиката стремежът ми е под 200 ms
Нужно подобрение800 ms – 1800 msВидимо забавяне на LCP; конверсиите падат
Слаб> 1800 msСериозен сървърен или мрежов проблем

Има и важен контекст: TTFB зависи силно от географията. Потребител от София, който удря origin сървър в us-east-1, ще има минимум 120 ms RTT само за TCP, преди сървърът да направи каквото и да е. Това е една от причините полевите данни (CrUX, RUM) винаги да са по-високи от lab данните (Lighthouse от една машина в US).

Как да измерите TTFB правилно

Има три различни сценария за измерване на TTFB и всеки от тях изисква различен инструмент. Не ги бъркайте. Често виждам екипи, които оптимизират lab TTFB и не разбират защо CrUX данните не мърдат.

1. Lab измерване (синтетично)

За бърза проверка, използвайте curl с timing формат. Това ми е първият инструмент при всеки одит:

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

Това разбива целия HTTP цикъл по етапи. Ако time_starttransfer - time_appconnect е голямо число, значи сървърът е виновникът, а не мрежата.

2. Browser RUM (поле)

За реални потребителски данни използвам PerformanceObserver с navigation entry-та. Това е същият подход, който библиотеката web-vitals.js ползва за нейните onTTFB() callback-и:

// Минимален TTFB колектор
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // responseStart е момента, в който пристигна първият байт
    const ttfb = entry.responseStart - entry.startTime;
    // Праща стойността към аналитика
    navigator.sendBeacon('/rum', JSON.stringify({
      metric: 'TTFB',
      value: ttfb,
      url: location.pathname,
      navType: entry.type, // navigate, reload, back_forward, prerender
    }));
  }
}).observe({ type: 'navigation', buffered: true });

3. Полеви данни от CrUX

За проектите си винаги поглеждам CrUX чрез PageSpeed Insights API или BigQuery dataset-а. Това е единственото "истинско" число: реални Chrome потребители, реални мрежи, реални 28-дневни прозорци. Lab измерванията са полезни за бързи итерации, но не и за SLO.

Анатомия на TTFB: къде отива времето

Преди да оптимизирате каквото и да е, разбийте TTFB-то на компонентите му. Според MDN документацията за PerformanceNavigationTiming, навигационното API ви дава следните timestamp-и (всички в милисекунди от startTime):

  • Redirect time: redirectEnd - redirectStart. Често забравян, но 301 към 302 верига може да добави 200 до 400 ms.
  • DNS lookup: domainLookupEnd - domainLookupStart. Обикновено 20 до 120 ms на студен cache.
  • TCP connect: connectEnd - connectStart. Около 1 RTT.
  • TLS handshake: connectEnd - secureConnectionStart. 1 RTT с TLS 1.3, 2 RTT с TLS 1.2.
  • Server processing (същинският TTFB): responseStart - requestStart. Тук обикновено е истинският проблем.

В моя опит разпределението при типичен SSR сайт (преди оптимизация) изглежда така: 30 ms DNS, 40 ms TCP, 40 ms TLS, 500 до 900 ms server processing. Server processing-ът е 80% от проблема, затова всички следващи секции се концентрират върху него.

CDN и edge кеширане на HTML

Най-голямата победа за TTFB-то през 2026 г. идва от едно решение: кеширайте HTML на edge. Не само статичните asset-и (всички правят това), а самия HTML отговор. Това трансформира TTFB от 600 до 900 ms (origin hit) на 30 до 80 ms (edge hit).

Тактиката зависи от стека. За статични или ISR (Incremental Static Regeneration) сайтове на оптимизирани JavaScript framework-и като Next.js, кеширането е по подразбиране. За динамични страници трябва експлицитно Cache-Control или CDN-Cache-Control header. Ето минимална конфигурация за Cloudflare:

// Cloudflare Worker, кеш на HTML с stale-while-revalidate
export default {
  async fetch(request, env, ctx) {
    const cache = caches.default;
    const cacheKey = new Request(request.url, request);

    // Опит за hit
    let response = await cache.match(cacheKey);
    if (response) {
      return response;
    }

    // Miss, fetch към origin
    response = await fetch(request);

    // Кеш само за HTML отговори със статус 200
    const contentType = response.headers.get('content-type') || '';
    if (response.status === 200 && contentType.includes('text/html')) {
      const cloned = response.clone();
      // Кешираме за 60 секунди, SWR за 24 часа
      cloned.headers.set(
        'Cache-Control',
        'public, max-age=60, stale-while-revalidate=86400'
      );
      ctx.waitUntil(cache.put(cacheKey, cloned));
    }

    return response;
  },
};

Тактиката stale-while-revalidate е критична. Тя позволява edge-ът да върне стара версия мигновено (TTFB около 30 ms), докато във фонов режим refresh-ва от origin. Потребителят винаги вижда бърз отговор, и то до 24 часа след инвалидирането.

Оптимизации на сървъра и базата данни

Когато edge кешът miss-ва или не може да се ползва (логнат потребител, dynamic page), всичко зависи от това колко бързо origin-ът връща HTML. В моите traces 70 до 90% от server processing времето отива в database queries. Ето тактиките, които работят последователно.

Профилирайте, преди да оптимизирате

Включете slow query log на базата данни с праг 50 ms. За PostgreSQL: log_min_duration_statement = 50. За MySQL: long_query_time = 0.05. Гарантирам, че ще намерите N+1 заявка в първите 10 минути. (Поне аз винаги намирам.)

Кеширайте на ниво приложение

Redis или Memcached пред базата за често четени, рядко променяни данни (config, navigation menu, product categories). Заявка към Redis отнема под 1 ms; към Postgres с join около 20 до 80 ms.

Преместете runtime-а близо до потребителя

Vercel Edge Runtime, Cloudflare Workers и AWS Lambda@Edge изпълняват кода в десетки локации по света. Когато можете да генерирате HTML без heavy database заявки (или с edge-replicated KV/D1 store), TTFB пада до 50 до 100 ms глобално.

Streaming SSR

Вместо да чакате целия HTML преди да върнете първия байт, ползвайте React Server Components или Astro server islands със streaming. Това намалява TTFB драматично: първият байт идва веднага, а content-ът се stream-ва прогресивно. За по-дълбоко разглеждане на тази тема препоръчвам статията ми за LCP оптимизация, където разглеждам как streaming влияе върху LCP.

HTTP/3, Brotli и Early Hints

Тези три подобрения на транспортния слой са най-добрата ROI за TTFB през 2026 г., защото всички major CDN-и ги поддържат out of the box.

HTTP/3 (QUIC)

HTTP/3 ползва UDP и QUIC, които елиминират TCP head-of-line blocking и поддържат 0-RTT connection resumption. На стабилни мрежи разликата с HTTP/2 е малка (10 до 30 ms), но на мобилни 4G/5G мрежи със загуба на пакети HTTP/3 е забележимо по-бърз. Включването е едно чекбокс в Cloudflare/Fastly dashboard. Истински "free win", ако ме питате.

Brotli компресия

Brotli (ниво 4 до 6) дава 15 до 25% по-малък HTML спрямо gzip при сходен CPU cost. Това директно намалява transfer time на първия chunk. За статични файлове ползвайте ниво 11 (offline, веднъж). За dynamic HTML ползвайте ниво 4 или 5 (real-time, без забележим CPU overhead).

Early Hints (103)

Early Hints е HTTP status 103, който позволява на сървъра да изпрати Link: rel=preload headers докато още генерира HTML отговора. Браузърът започва да тегли CSS, шрифтове и LCP image едновременно с генерирането на HTML. Резултат: 100 до 300 ms подобрение на LCP при сайтове с тежък SSR. Cloudflare и Fastly го поддържат напълно през 2026 г.

# Express.js пример с Early Hints
app.get('/', (req, res) => {
  // Изпращаме 103 преди да започнем тежката работа
  res.writeEarlyHints({
    link: [
      '</styles/main.css>; rel=preload; as=style',
      '</fonts/inter.woff2>; rel=preload; as=font; crossorigin',
      '</hero.avif>; rel=preload; as=image; fetchpriority=high',
    ],
  });

  // Сега правим бавните неща (DB заявки, рендериране)
  const data = await fetchHeavyData();
  res.render('home', data);
});

TTFB vs FCP vs LCP: каква е разликата?

Тези три метрики често се бъркат, но измерват различни моменти от живота на страницата. Ето таблица за бърза справка:

МетрикаКакво измерваКога се "случва"Добра стойност (p75)
TTFBВреме до първия байт от сървъраПреди дори да започне parsing< 800 ms (стремеж < 200 ms)
FCPВреме до първия видим pixelСлед CSS parsing и initial layout< 1.8 s
LCPВреме до най-големия видим елементСлед като главното съдържание е отрендирано< 2.5 s

Връзката е каскадна: TTFB ⊂ FCP ⊂ LCP. Не можете да имате LCP 1.5 s, ако TTFB-то ви е 1.8 s. Буквално невъзможно. Това е причината винаги да започвам всеки одит с измерване на TTFB: ако той не е под 600 ms, LCP оптимизациите са губене на време. Подобна динамика разглеждам и в ръководството за INP оптимизация, където main thread е аналогичния "bottleneck" за интерактивност.

Често задавани въпроси

Влияе ли TTFB на SEO ранкинга?

TTFB не е директен ranking фактор, но е компонент на LCP, който е Core Web Vital и е ranking сигнал. Висок TTFB води до висок LCP, а Google понижава страници с лош Core Web Vitals score за p75 на полето.

Как да намаля TTFB на WordPress сайт?

Активирайте full-page caching с плъгин като WP Rocket или LiteSpeed Cache, сложете Cloudflare пред origin-а с APO (Automatic Platform Optimization), използвайте Brotli и PHP 8.3+ с OPcache. Това обикновено сваля TTFB от 1.2 s на 100 до 200 ms.

Защо моят TTFB е добър в Lighthouse, но лош в CrUX?

Lighthouse мери от една машина с бърза мрежа близо до сървъра, докато CrUX събира данни от реални потребители с разнообразни мрежи, устройства и географии. Полевите данни винаги са по-високи. Решението е географски разпределено edge кеширане и RUM измерване, не сляпо доверяване на lab числата.

Каква е разликата между TTFB и server response time?

Server response time е само частта от TTFB, която сървърът контролира: времето между получаването на заявката и изпращането на първия байт. TTFB включва и DNS, TCP, TLS, и мрежовото време за първия байт. Може да имате 50 ms server response time, но 400 ms TTFB заради бавна DNS резолюция или далечен origin.

Помага ли HTTP/3 за TTFB, ако сървърът е бавен?

Не значително. HTTP/3 спестява 1 RTT на handshake-а (около 30 до 100 ms според мрежата), но ако сървърното processing време е 800 ms, то си остава 800 ms. HTTP/3 е "free win" при connection setup, не е заместител на сървърна оптимизация.

Alex Petrov
За Автора Alex Petrov

Web performance engineer who treats every millisecond as a personal challenge. Has profiled more sites than he can count.