Нажатие Enter запускает не один HTTP-запрос, а цепочку из нескольких сетевых, серверных и браузерных подсистем. Внутри разбор критического пути от DNS до рендеринга и ответ на вопрос почему Senior Fullstack читает весь маршрут целиком, а не только profiler своего фреймворка.


Содержание


TTFB ≠ скорость страницы: что именно измеряется

Открытие сайта — это не один HTTP-запрос. DNS, CDN, TLS, reverse proxy, application server, кэш, база данных и браузер — уже несколько независимых подсистем, которые частично работают параллельно. Даже приложение, написанное одним разработчиком на одном сервере, каждый раз проходит через этот маршрут целиком.

«200 мс» в этом материале — не обещание, что вся страница отрисуется за 200 мс. Это модель для анализа конкретного участка: Time to First Byte (TTFB), то есть времени до первого байта ответа сервера. web.dev рекомендует ориентироваться на ≤800 мс как общий ориентир для большинства сайтов, подчёркивая, что это не Core Web Vital: значение нужно интерпретировать в связке с FCP и LCP.

После TTFB браузеру ещё предстоит: скачать HTML полностью, обнаружить и загрузить CSS, JS, изображения и шрифты, выполнить JavaScript, построить Render Tree, сделать layout, paint, compositing. Для SPA это особенно критично: низкий TTFB может быть практически бесполезен, если браузеру предстоит большой объём клиентского рендеринга перед тем, как пользователь увидит контент.

Путь запроса схематично:

Браузер

  ├── cache / Service Worker?

  ├── DNS → IP

  └── TCP или QUIC + TLS

        ↓

CDN / Edge

  ├── cache hit → ответ

  └── cache miss

        ↓

Reverse Proxy → App Server

  ├── Redis / cache

  ├── PostgreSQL

  └── business logic

        ↓

HTML / JSON

        ↓

Браузер: DOM → CSSOM → JS → Layout → Paint → Compositing

        ↓

LCP

Уже здесь понятно: TTFB = 200 мс совсем не означает, что пользователь увидел готовую страницу через 200 мс.


Browser cache и DNS: первый шаг

Пользователь вводит https://shop.example.com/catalog/42. До отправки первого байта в сеть браузер проверяет несколько локальных источников: HTTP cache, memory cache, disk cache, Service Worker, уже открытое соединение, DNS cache.

Поэтому два последовательных открытия одного URL дают разные waterfall — и это не баг. MDN отмечает, что DNS-результаты кэшируются, а разные hostname для шрифтов, изображений, скриптов и аналитики могут потребовать отдельных DNS lookup, каждый со своим TTL.

Для performance-инженера здесь важен не только сам протокол, но и число hostname на странице, длина CNAME-chain, география резолвера. При холодном старте (cold start) — полная цепочка рекурсивного резолвинга — DNS занимает 50+ мс. При закэшированном значении — 0 мс. Именно поэтому «DNS — главный тормоз» редко оказывается правдой: проблема почти всегда глубже.


TCP, QUIC и TLS: транспортный слой под капотом

Если соединения нет в кэше, браузеру нужно установить транспорт. Для классического HTTPS:

TCP handshake → TLS handshake → HTTP

Для HTTP/3:

QUIC (включает TLS 1.3) → HTTP/3

HTTP/3 — это не просто «HTTP/2, но быстрее». QUIC объединяет транспорт и TLS 1.3 в одном протоколе, реализует stream multiplexing и connection migration. RFC 9114 фиксирует low-latency connection establishment как одно из ключевых свойств стека: бороться с connection latency можно уже не только на уровне приложения, но и на уровне выбора протокола.

Для тёплого соединения TLS добавляет ≈0 мс — 0-RTT resumption и connection reuse делают повторный запрос значительно дешевле первого. Именно поэтому интерпретировать замеры производительности нужно с явным указанием типа соединения: cold или warm. Разница между ними в waterfall — принципиальная.


CDN и edge: самый быстрый запрос — тот, что не дошёл до origin

В production-архитектуре между браузером и backend почти всегда стоит CDN:

Browser → Edge

  ├── cache HIT → ответ без round trip к origin

  └── cache MISS

        ↓

Load Balancer → Reverse Proxy → Application → DB

Если HTML или JSON уже закэширован на edge, запрос не доходит ни до приложения, ни до базы данных. Принцип прост: самый быстрый database query — тот, что не выполнялся. И второй: самый быстрый backend — тот, до которого запрос не дошёл.

Но CDN не спасёт динамический запрос, если ответ помечен Cache-Control: private, привязан к сессии или содержит персонализированный HTML. В таких случаях CDN вынужден идти к origin: выигрыш сводится к geographic proximity, но round trip до приложения никуда не исчезает.


Backend: routing, middleware, база данных

Допустим, cache miss. Запрос добрался до приложения:

GET /products/42 HTTP/2

Host: shop.example.com

Cookie: session=abc123

Accept: text/html

Внутри сервера путь:

router → middleware → authentication → business logic

  ↓

Redis (cache check)?

  ↓

PostgreSQL: SELECT id, name, price FROM products WHERE id = 42

  ↓

template / SSR → response

Проблема начинается, если SQL выполняется 300 мс без индекса, порождает N+1 queries, блокирует connection pool или ждёт внешний API. В таком сценарии оптимизация React-компонентов или сокращение bundle size полностью нерелевантны: пользователь ждёт не frontend, а ответа сервера.

N+1 queries — классическая ловушка: 1 запрос за списком объектов плюс N отдельных запросов для каждого из них. При 100 товарах и 10 мс на запрос — уже секунда задержки только на уровне базы. Типичное решение: один запрос с JOIN и грамотным индексом, либо батч-загрузка через WHERE id IN (...).


Браузер получает ответ: rendering pipeline

Браузер получает HTML — и здесь начинается уже не сетевая проблема, а браузерная. MDN подчёркивает: первоначальный HTTP-ответ порождает новые запросы к CSS, JavaScript, изображениям и другим sub-resources.

HTML → DOM

CSS  → CSSOM

DOM + CSSOM → Render Tree → Layout → Paint → Compositing

Критический путь рендеринга (critical rendering path) — ресурсы, без которых браузер не может показать первый пиксель. Render-blocking JS и CSS удлиняют этот путь напрямую. LCP (Largest Contentful Paint) — метрика Core Web Vitals, которая фиксирует момент, когда пользователь увидел главный контент. Между 200 OK и LCP может пройти секунда и более. Фраза «сервер ответил 200 OK» не означает «сайт загрузился».


Практический кейс: как читать waterfall

Сценарий: интернет-магазин со стеком User → CDN → Nginx → Node.js/Nest.js → PostgreSQL.

Наблюдаемые метрики:

  • TTFB = 780 мс

  • LCP = 2,9 с

Первый инстинкт команды — уменьшить bundle React. Но waterfall в Chrome DevTools показывает другое:

DNS       12 мс

Connect    8 мс

TLS       11 мс

Request    3 мс

Waiting  746 мс  ← здесь проблема

Receive    7 мс

Frontend ещё не начал работать. Profiling backend:

controller        5 мс

auth             12 мс

Redis             3 мс

PostgreSQL      680 мс

serialization     8 мс

Причина — тяжёлый SQL на таблице с миллионом строк без индекса. После добавления:

CREATE INDEX idx_products_category_created

ON products(category_id, created_at DESC);

Условный результат:

PostgreSQL: 680 мс → 24 мс

TTFB:       780 мс → 118 мс

Теперь оптимизация JS bundle и hydration становятся актуальными. Именно в таком порядке.

Стартовый инструмент для диагностики без DevTools:

curl -o /dev/null -s \

  -w "DNS:      %{time_namelookup}\n\

Connect:   %{time_connect}\n\

TLS:       %{time_appconnect}\n\

TTFB:      %{time_starttransfer}\n\

Total:     %{time_total}\n" \

  https://example.com

Chrome DevTools → Network → Timing даёт полный waterfall: DNS, Connect, TLS, Waiting (TTFB), Content Download, а также Initiator и connection ID для анализа параллелизма запросов. Именно с этих двух инструментов начинается любая осмысленная диагностика производительности.


Четыре подводных камня

«200 OK означает, что сайт быстрый»

HTTP status 200 ничего не говорит о времени backend, TTFB, размере JS-bundle или моменте LCP. Это разные измерения из разных слоёв системы — подменять одно другим не стоит.

«DNS — главный тормоз»

На современных системах DNS часто кэширован: браузером, ОС, локальным резолвером. Если DNS занимает 5 мс, а PostgreSQL — 500 мс, оптимизация DNS ничего принципиально не изменит. Диагностику стоит начинать с Waiting-фазы в waterfall.

«Нужно просто поставить CDN»

CDN эффективен там, где контент действительно кэшируется. Динамические запросы с Cookie или Cache-Control: private всё равно идут к origin: выигрыш сводится к географическому proximity, но не устраняет latency самого backend.

«React отвечает за скорость сайта»

React — только часть pipeline:

  • DNS, TCP, TLS: network layer;

  • TTFB: network + backend;

  • DB query time: backend/data layer;

  • LCP: browser + network + server;

  • INP: browser/main thread.

React предоставляет <Profiler> для измерения rendering performance дерева компонентов — но это один слой из многих, никак не влияющий на время SQL-запроса.


Fullstack в вакансиях 2026 года

В актуальных вакансиях заметны характерные технологические связки. «Обычные подозреваемые» – TypeScript, React, Python, PostgreSQL, CI/CD, Git, Kubernetes. Fullstack JavaScript-позиции: JavaScript, React, TypeScript, Node.js, Next.js, NestJS, Express, PostgreSQL. Senior с .NET-стеком: ASP.NET Core, TypeScript, React, Webpack, MS SQL/PostgreSQL, Docker, docker-compose, Python.

Рынок 2026 года всё меньше выглядит как «я умею React» и всё больше как «я провожу feature от браузера до базы и production-инфраструктуры». Важная оговорка: единого обязательного стека не существует. Python, .NET, Ruby и другие комбинации по-прежнему живут в production-вакансиях — рынок становится полицентричным, а не монолитным.

Stack Overflow Developer Survey 2025 фиксирует отдельно: Docker совершил заметный скачок использования, среди web-фреймворков продолжают лидировать React, Node.js и Next.js, вырос интерес к FastAPI.

Актуально для Middle:

  • JavaScript/TypeScript;

  • React, Vue или другой production frontend;

  • REST/API, SQL, PostgreSQL;

  • Git, базовый Docker;

  • понимание HTTP и основ сетей;

  • debugging через Chrome DevTools;

  • тестирование, понимание deployment.

Senior — дополнительно:

  • system design;

  • performance и observability;

  • caching, queues;

  • CI/CD;

  • database optimization: query plans, индексы, connection pooling;

  • trade-offs между SSR/CSR/SSG;

  • способность диагностировать проблему между слоями стека.

Именно последний пункт — ключевой. Senior видит не страницу. Он видит цепочку подсистем, каждая из которых способна добавить следующие 50 мс.


Где закрыть пробелы системно

Три программы подобраны не по принципу «лучший курс», а по соответствию конкретным участкам разобранного пути.


Если раздел про DNS/TLS и диагностику запроса обнаружил пробелы

HTTP, асинхронность, REST API и Chrome DevTools системно покрывает программа «Fullstack-разработчик на Node.js» от Хекслета. По данным каталога Хабр Карьеры, программа включает: Node.js, React, JavaScript, HTTP, REST API, базы данных, Chrome DevTools, SQL, Git/GitHub, Ubuntu. Длительность — 16 месяцев, стоимость — 161 250 ₽.

Ограничение: Node.js/React-стек делает программу менее универсальной для разработчика на Python или .NET; фундаментальные темы могут быть избыточны для опытного специалиста, которому нужно закрыть конкретный пробел.

Подробности о программе — в каталоге Хабр Курсов


Если проблема оказалась в серверной части, а не во frontend

В программе «Профессия Fullstack-разработчик на Python» от Skillfactory есть отдельные блоки по Django, PostgreSQL, Linux, Docker, Nginx, Gunicorn и CI/CD. По данным каталога Хабр Карьеры: 14 месяцев, от 4 829 ₽/мес., 173 844 ₽ при единовременной оплате.

Ограничение: Python/Django-centric стек. Для разработчика в TypeScript/Node.js production — другой технологический маршрут, не прямой аналог первой программы.

За подробностями идем в каталог Хабр Курсов


Если хочется собрать всю цепочку browser → API → DB → deployment в один проект

Программа «Фулстек-разработчик» от Яндекс Практикума последовательно проходит React/TypeScript, Node.js, REST, PostgreSQL, Docker, deployment и security. По данным каталога Хабр Карьеры: 16 месяцев, от 8 287 ₽/мес. или 203 000 ₽ единовременно.

Ограничение: для Middle/Senior с конкретной точечной задачей — например, разобраться только с HTTP/performance — прохождение всей программы избыточно. Ценность выше как систематизация fullstack-базы с нуля, чем как точечный performance bootcamp.

Программа в каталоге Хабр Курсов


FAQ

Правда ли, что весь сайт может загрузиться за 200 мс?

TTFB может составлять 200 мс и менее — особенно при тёплом соединении и cache hit на edge. Но это только время до первого байта ответа. После него браузеру предстоит HTML parsing, CSS, JavaScript, layout, paint и compositing. Для большинства production-сайтов LCP приходится через 1-3 секунды после нажатия Enter.

Где смотреть waterfall на реальном сайте?

Chrome DevTools → вкладка Network. Ключевые данные: Waterfall (визуальная шкала), Timing (DNS, Connect, TLS, Waiting, Receiving), Initiator (что инициировало запрос), connection ID. Дополнительно — Lighthouse для автоматического аудита Core Web Vitals, FCP и LCP.

Что такое N+1 queries и почему это важно знать fullstack-разработчику?

N+1 queries — ситуация, когда приложение делает 1 запрос за списком объектов, а затем N отдельных запросов для каждого. При 100 товарах и 10 мс на запрос — уже секунда задержки только на уровне базы данных. Типичное решение: один запрос с JOIN и грамотным индексом, либо батч-загрузка с WHERE id IN (...). Это проблема не React и не Nginx — это проблема слоя данных, которую видно только при чтении всей цепочки.