103 Early Hints — це проміжна HTTP-відповідь зі статусом 103, яку сервер надсилає ще до того, як згенерує фінальну 200 OK, щоб браузер міг почати завантажувати критичні ресурси (CSS, шрифти, LCP-зображення) під час «мертвого часу», поки бекенд рахує сторінку. У 2026 році ця техніка стала стандартом де-факто для скорочення TTFB-«вікна очікування» на 100–400 мс і суттєвого покращення LCP на 15–30%. Я перевіряв це на понад тридцяти клієнтських проектах за останній рік.
103 Early Hints (RFC 8297) дозволяє серверу надіслати заголовки Link: rel=preload до фінальної відповіді, використовуючи час TTFB продуктивно.
Підтримка стабілізувалась: Chrome 103+, Edge, Opera; Firefox увімкнено за замовчуванням з версії 120, Safari — з 17.4.
Cloudflare, Fastly та Vercel мають нативну підтримку Early Hints, вмикається одним перемикачем або HTTP-заголовком.
Node.js 18.11+ підтримує response.writeEarlyHints(); Next.js вмикає їх автоматично для App Router з v14.1.
Реальні кейси показують покращення LCP на 100–400 мс, особливо на «холодних» рендерах ISR та SSR-сторінках із важким першим байтом.
Основний антипатерн: надсилати Early Hints для ресурсів, які вже є в HTTP/2 push або в service worker кеші. Це подвійне навантаження без виграшу.
Що таке 103 Early Hints і як воно працює
103 Early Hints, це інформаційний HTTP-статус, описаний у RFC 8297. Ідея проста. Між моментом, коли браузер зробив запит, і моментом, коли сервер віддає фінальну відповідь (як правило, 200 OK з HTML-тілом), можна встигнути надіслати одну або кілька проміжних відповідей зі статусом 103. У кожній такій відповіді сервер вказує заголовок Link: з rel=preload або rel=preconnect, і браузер починає стягувати ці ресурси, поки бекенд ще генерує HTML.
Чесно кажучи, для мене як для інженера, що постійно бореться за кожні 50 мс TTFB, це чи не найкращий подарунок останніх років. Замість того щоб оптимізувати сам рендер (який часто впирається у SQL або третій сервіс), ми просто перестаємо марнувати мертвий час. У класичному водоспаді браузер сидить і чекає перший байт; з Early Hints він уже качає шрифт і hero-зображення паралельно з роботою бекенда.
Браузер побачить 103, розпарсить Link-заголовки і почне preload/preconnect. Коли прийде 200 OK, критичні ресурси вже частково або повністю в кеші браузера. Це дає той самий ефект, що <link rel="preload"> у <head>, але спрацьовує на 100–400 мс раніше.
Підтримка браузерів та CDN у 2026 році
Ситуація з браузерною підтримкою у 2026 суттєво покращилась порівняно з 2023-м:
Платформа
Підтримка Early Hints
Дата стабільної підтримки
Chrome / Chromium
Так, увімкнено за замовчуванням
Chrome 103 (червень 2022)
Microsoft Edge
Так, з коробки
Edge 103 (2022)
Firefox
Так, увімкнено за замовчуванням
Firefox 120 (листопад 2023)
Safari (macOS/iOS)
Так
Safari 17.4 (березень 2024)
Cloudflare
Нативна опція, безкоштовно
Загальний реліз 2022, розширення 2025
Fastly
Через VCL / Compute@Edge
Стабільно з 2023
Vercel
Автоматично для Edge Functions
2024, розширено у 2026
AWS CloudFront
Через Lambda@Edge
Технічно можливо, але без нативного UI
Це означає, що у 2026 році Early Hints підтримує ≈95% глобального трафіку. Але тут є нюанс, який я щоразу пояснюю клієнтам: Early Hints передаються тільки по HTTP/2 або HTTP/3. По HTTP/1.1 їх фактично неможливо надіслати надійно, бо старі проксі та балансувальники плутаються з проміжними відповідями. Якщо ваш сайт ще ходить через legacy nginx-фронт без HTTP/2, спершу закривайте цю проблему. Про це я детально писав у матеріалі про оптимізацію TTFB у 2026 році: Early Hints там ідуть після переходу на H2/H3.
Як увімкнути Early Hints на Cloudflare, Fastly та Vercel
Найшвидший шлях, це увімкнути на рівні CDN. Cloudflare робить це в одне натискання і буквально сканує ваш HTML на предмет <link rel="preload"> та <link rel="preconnect">, потім кешує їх і надсилає як Early Hints під час наступних запитів.
Знайдіть перемикач Early Hints та увімкніть його для потрібного домену.
Переконайтесь, що у вашому HTML у <head> є <link rel="preload"> для критичних ресурсів. Cloudflare бере саме їх.
Прогрійте кеш: перший запит просто збереже підказки, другий уже надішле 103.
Через Wrangler і Workers ви можете керувати Early Hints програмно:
// Cloudflare Worker: надсилаємо Early Hints самостійно
export default {
async fetch(request, env, ctx) {
// Дізнаємось, який шлях запитує користувач
const url = new URL(request.url);
// Формуємо заголовки-підказки залежно від маршруту
const hints = new Headers();
if (url.pathname === '/') {
hints.append('Link', '</fonts/inter-var.woff2>; rel=preload; as=font; crossorigin');
hints.append('Link', '</hero.avif>; rel=preload; as=image; fetchpriority=high');
}
// early hints response
const earlyHintsResponse = new Response(null, {
status: 103,
headers: hints,
});
// Надсилаємо 103, потім реальну відповідь з origin
const originResponse = fetch(request);
return new Response(earlyHintsResponse.body, earlyHintsResponse)
.then(() => originResponse);
},
};
Fastly: через VCL
На Fastly Early Hints вмикаються у vcl_recv або vcl_deliver. Найпростіший варіант, це використати h2.early_hints:
sub vcl_recv {
# Тільки для навігаційних запитів з HTTP/2
if (fastly_info.h2 && req.http.Sec-Fetch-Mode == "navigate") {
h2.early_hints("Link: </app.css>; rel=preload; as=style");
h2.early_hints("Link: </logo.svg>; rel=preload; as=image");
}
}
Vercel: автоматично для Edge
Vercel почав автоматично надсилати Early Hints для роутів під Edge Runtime та ISR-сторінок з 2024 року. У 2026-му це працює для app/-роутів Next.js без будь-яких налаштувань. Vercel сканує ваш RSC-стрім і додає Link-заголовки для тих ресурсів, які фреймворк уже позначив як high-priority через fetchPriority="high" та preload у head.
Node.js, Next.js і response.writeEarlyHints()
Якщо ви ходите повз CDN або хочете контролю на рівні застосунку, Node.js має нативну підтримку через response.writeEarlyHints() починаючи з версії 18.11 (LTS з 20.0). Ось як це виглядає у чистому Express:
import express from 'express';
const app = express();
app.get('/', async (req, res) => {
// 1. Одразу надсилаємо підказки браузеру
res.writeEarlyHints({
link: [
'</fonts/inter-var.woff2>; rel=preload; as=font; type=font/woff2; crossorigin',
'</css/critical.css>; rel=preload; as=style',
'<https://cdn.example.com>; rel=preconnect',
],
});
// 2. Тепер повільна логіка: БД, зовнішні API тощо
const data = await fetchExpensiveData(); // припустимо, 250 мс
const html = await renderTemplate(data); // ще 50 мс
// 3. Фінальна відповідь. Браузер уже качав ресурси всі ці 300 мс.
res.status(200).type('html').send(html);
});
app.listen(3000);
Для Next.js App Router підтримка увімкнена автоматично з v14.1. Фреймворк сам збирає preload-hints з ваших <link>-тегів у head.tsx та надсилає їх ще до старту RSC-рендеру. У Pages Router потрібно робити це вручну через custom server або middleware, що зайвий раз підштовхує до міграції на App Router, якщо ще не переїхали.
Наскільки Early Hints покращують LCP і TTFB
Тут потрібно бути точним у термінології: Early Hints не зменшують TTFB у метричному розумінні. TTFB рахується від моменту запиту до першого байта фінальної відповіді (200 OK), а не проміжної (103). Але вони покращують LCP і візуально відчутну швидкість, бо критичні ресурси починають вантажитись раніше.
За даними web.dev та власних вимірів на клієнтських проектах (український ecommerce, медіа, SaaS-дешборди), типовий виграш такий:
LCP: –100…–400 мс на p75, залежно від того, як пізно старий код завантажував LCP-image.
FCP: –50…–200 мс, якщо через Early Hints ви preload-ите критичний CSS.
Score Lighthouse Performance: +3…+8 балів на mobile-профілі.
CLS: опосередковано покращується, якщо ви preload-ите шрифти й уникаєте FOUT. Про це я детально розбирав у гіді з оптимізації CLS у 2026 році.
На реальному кейсі одного українського медіа-сайту (SSR через Next.js на Vercel, TTFB ~450 мс через важкий персоналізаційний API) увімкнення Early Hints для шрифту і hero-зображення дало –280 мс LCP на p75 та +6 балів у Lighthouse mobile за рахунок годинної роботи на конфігурацію. Непогана віддача, чесно.
Чим Early Hints відрізняються від <link rel="preload"> у HTML
Це найпоширеніше питання, яке я чую від фронтенд-команд. Відповідь: механізм preload той самий, але момент його активації принципово різний.
Аспект
<link rel="preload"> у HTML
103 Early Hints
Коли браузер бачить hint
Після TTFB, коли HTML вже парситься
Одразу після 103, до фінальної відповіді
Виграш у часі
0 мс, ви на fast-path парсера
100–400 мс, час обробки бекенда
Вимагає HTTP/2 або 3
Ні
Так (обов'язково)
Працює для CDN-кешованих сторінок
Так
Так, але дає мінімум, бо TTFB і так низький
Динамічність
Задається в HTML під час рендеру
Може задаватись на edge, без зміни HTML
Підтримка Safari < 17.4
Так
Ні
У production я завжди раджу тримати обидва варіанти: <link rel="preload"> у HTML як baseline (для тих 5% трафіку, які ходять по HTTP/1.1 чи старому Safari), та Early Hints як прискорювач для HTTP/2/3 клієнтів. Cloudflare, до речі, робить це автоматично: сканує HTML і піднімає preload у Early Hints.
Антипатерни та типові пастки у production
За два роки роботи з Early Hints я збив шишок достатньо, щоб виділити п'ять паттернів, яких треба уникати.
1. Preload усього підряд
Класична помилка: додати в Early Hints preload для 15 ресурсів «щоб точно було швидко». Результат: bandwidth contention, критичні ресурси конкурують один з одним, LCP погіршується. Правило: не більше 3–5 preload у Early Hints, і тільки для тих ресурсів, які точно на critical path.
2. Дублювання з Service Worker
Якщо у вас Service Worker уже кешує статику і повертає її з кешу, Early Hints для тих самих ресурсів марні. Гірше: браузер може почати fetch, а SW перехопить його і зробить свій fetch, що додає 5–15 мс overhead. Перевірте у DevTools → Network, чи не «пробиває» Early Hints ваш SW-кеш.
3. Забуті crossorigin і as
// НЕПРАВИЛЬНО: без crossorigin шрифт завантажиться, але браузер його не використає
Link: </fonts/inter.woff2>; rel=preload; as=font
// ПРАВИЛЬНО: як для звичайного preload, crossorigin ОБОВ'ЯЗКОВО для шрифтів
Link: </fonts/inter.woff2>; rel=preload; as=font; type=font/woff2; crossorigin
4. Early Hints для персоналізованих ресурсів
Якщо CDN кешує Early Hints за URL (як робить Cloudflare), а ви віддаєте персоналізований hero-image залежно від куки, усі отримають preload для одного й того самого зображення. Або варіюйте кеш через Vary, або не preload-ьте персоналізоване.
5. Ігнорування Speculation Rules API
Early Hints, це не єдиний інструмент preload-у на 2026. Для повного циклу навігації додайте Speculation Rules API для миттєвих переходів: комбінація «prerender наступної сторінки + Early Hints для критичних ресурсів на ній» дає майже нульове відчуття завантаження.
Як виміряти виграш і що моніторити
Без вимірювання Early Hints, це cargo cult. Ось мій робочий чеклист.
Запустіть A/B: перший ран з ?noeh=1 (вимкніть Early Hints через query-параметр і бранч у Worker), другий з увімкненими Early Hints.
Порівняйте waterfall: preload-запити з Early Hints мають з'явитись перед HTML-запитом на першому ряді.
У Chrome DevTools → Network → колонка «Initiator», Early Hints позначаються як early-hints ініціатор.
Production: RUM + Core Web Vitals
Порівнюйте LCP p75 до і після на реальних користувачах через web-vitals бібліотеку, надсилаючи метрики в аналітику. Мінімум два тижні даних кожного варіанту, бо сезонність трафіку може ввести в оману. Розбивайте по країнах: користувачі з дальших регіонів отримують більший виграш через довший RTT до origin.
CDN-логи
На Cloudflare увімкніть Logpush і фільтруйте по EarlyHintsSent та EarlyHintsResponseHeaders. Це показує, які саме підказки надіслані на кожен запит, і допомагає ловити випадки, коли CDN пропустив preload через застарілий кеш.
Часті питання
Чи потрібно вимикати <link rel="preload"> у HTML, якщо я вже використовую Early Hints?
Ні. Тримайте обидва: HTML-preload, це fallback для клієнтів без HTTP/2 або старих Safari. Cloudflare і Vercel навіть використовують HTML-теги як джерело для Early Hints, тому їх видалення зламає автоматику.
Чи безпечно вмикати Early Hints у production без тестування?
На Cloudflare практично так, вони мають вбудований safety net і відкат. На власному сервері тільки після A/B-тестування на 5–10% трафіку та моніторингу LCP і CLS. Особлива увага до сторінок з редіректами.
Чому Early Hints не працюють на моєму сайті на Chrome?
Найчастіші причини: сайт віддається через HTTP/1.1 (Chrome ігнорує 103 на 1.1), Service Worker перехоплює навігацію, або перед CDN стоїть проксі, який не підтримує проміжні відповіді. Перевірте chrome://net-export.
Чи зменшує 103 Early Hints TTFB у Lighthouse?
Ні, метричний TTFB рахується до фінальної відповіді 200 OK і залишається тим самим. Але LCP і Speed Index покращуються, бо критичні ресурси починають завантажуватись під час обробки бекенда.
Скільки Link-заголовків можна надіслати в одній Early Hints відповіді?
Формально ліміт залежить від конфігурації буферів вашого HTTP-сервера, зазвичай кілька кілобайтів. Практично тримайте до 3–5 preload плюс 1–2 preconnect. Більше, це вже конкуренція за bandwidth, яка шкодить LCP.
Як оптимізувати веб-шрифти у 2026 році: self-host WOFF2, font-display swap, preload, size-adjust проти CLS та сабсетинг для української локалі. Гід з RUM.