Why TTFB is the floor
Time to first byte is how long the browser waits before the first byte of HTML arrives. Nothing can render, no image can be discovered, no script can run until then. An LCP of 2.5 seconds is impossible if TTFB is 1.8. Google's guidance is a TTFB under 800 milliseconds, and a site aiming for good LCP wants it well under 500.
It is also the metric most often blamed on "the server" without anyone measuring which of its parts is slow.
The parts
From the visitor's tap to the first byte:
- Redirects.
http://tohttps://,wwwto non-www, a trailing slash. Each is a full round trip before the real request begins. Two redirects on a mobile connection can be 400 milliseconds on their own. - DNS lookup. Resolving the domain. Usually fast; slow with an obscure DNS provider or a long CNAME chain.
- Connection. TCP handshake and TLS negotiation. One to two round trips. Longer for distant servers and for servers without TLS 1.3 or session resumption.
- Request to edge. If a CDN is in front, the request reaches the nearest edge node here. A cache hit returns the HTML now, and TTFB is done, typically under 100 milliseconds.
- Edge to origin. On a cache miss, the edge forwards the request to your origin server, which may be on another continent.
- Origin processing. The server generates the page: PHP running WordPress, a Node function rendering React, a database query. This is where "the server is slow" actually lives, and it ranges from 20 milliseconds to several seconds.
- Response start. The first byte travels back through the edge to the browser.
Measuring each part
In the browser: DevTools Network panel, click the HTML request, Timing tab. It shows Queueing, DNS, Initial connection, SSL, Request sent, Waiting (TTFB) and Content download. "Waiting" is steps 4 to 7 combined.
Redirects: the Network panel shows them as separate rows above the final request. Count them.
Cache hit or miss: response headers. cf-cache-status, x-vercel-cache, x-cache, age. A HIT means the origin was not involved; a MISS or DYNAMIC means it was, and the Waiting time is mostly origin.
Origin processing alone: Server-Timing headers, if your platform emits them, break down origin time. Otherwise, request the origin directly (bypassing the CDN via a hosts entry or an origin hostname) and compare.
From several places: a synthetic tool that tests from multiple regions shows whether TTFB is uniformly slow (origin) or slow only far from the server (no edge cache, or origin geography).
In the field: the web-vitals library's TTFB metric with attribution reports waiting time, DNS, connection and cache state from real visitors. Aggregate by country; distant visitors expose geography problems.
Managed WordPress hosting
Good managed hosts (Kinsta, WP Engine, Cloudways, SiteGround's upper tiers and peers) put a full-page cache in front of PHP. Cache hits return in tens of milliseconds regardless of how slow the theme is. Their TTFB problems are:
- Low cache hit rates. Pages excluded from cache by a cookie (a consent banner setting one, WooCommerce's session cookie on every page, a plugin's tracking cookie), by query strings from ad campaigns, or by a plugin sending no-cache headers. Fix the cookie and query handling; most hosts have settings for both.
- Cache misses being slow. The first visitor to a page after a purge waits for PHP. If PHP takes two seconds, that visitor's TTFB is two seconds. A persistent object cache (Redis), fewer plugins and a sane theme keep the miss under half a second.
- Purging too often. Every post save clearing the entire cache means the site is constantly cold. Configure targeted purges.
- No edge. Some hosts cache at a single data centre. Visitors on the other side of the world get the full latency. Put a CDN (Cloudflare or the host's) in front and cache HTML at the edge, not just assets.
- Uncacheable pages. Cart, checkout, account, logged-in views. These run PHP every time; their TTFB is the origin's speed, and the fixes are the origin ones.
Edge platforms and serverless functions
Vercel, Netlify, Cloudflare Pages and similar serve static and cached pages from the edge with TTFB typically under 100 milliseconds worldwide. Their TTFB problems are different:
- Dynamic routes rendering per request. A page that reads cookies or headers, or is not marked cacheable, runs a function on every request. Function cold starts add hundreds of milliseconds; the render itself adds more. Make pages static or cached where they can be (in Next.js,
use cacheon the shell with dynamic parts behind Suspense so the shell streams immediately). - Function region far from the data. A serverless function in one region calling a database in another adds a round trip per query. Co-locate them, or cache the data.
- Middleware doing too much. Edge middleware runs before every request; a slow fetch inside it delays every TTFB.
- Streaming not used. With Suspense and streaming, the shell's first byte arrives before slow data resolves. Without it, TTFB waits for the slowest fetch on the page.
- Cold starts. Rare paths and low-traffic sites see them more. Keep function bundles small; use the edge runtime for simple routes.
The fixes, in order
- Remove redirect chains. One redirect at most, from
httpand the non-canonical host straight to the final URL. - Cache HTML at the edge for every page that can be cached, and fix whatever is preventing hits.
- Make cache misses fast: object cache, fewer plugins, co-located data, streaming shells.
- Move dynamic work out of the critical path: personalisation client-side or behind Suspense; middleware minimal.
- Check DNS and TLS: a fast DNS provider, TLS 1.3, HTTP/2 or 3, OCSP stapling.
- Then, and only then, consider a faster origin plan. Most TTFB problems are caching and redirects, not CPU.
Where this fits
TTFB is the second number we read in a Core Web Vitals audit, after LCP itself, because a slow TTFB caps everything and its cause is usually a cache that is not hitting. The Network panel's Timing tab and one response header answer most of it in five minutes.