What is Time to First Byte (TTFB)?
Time to First Byte (TTFB) is a web performance metric that measures the duration between a browser's request and the first byte of the server's response.
What is Time to First Byte (TTFB)?
Time to First Byte (TTFB) is a performance metric that captures the elapsed time between a user's HTTP request and the moment the browser receives the first byte of the response from the server. It includes DNS lookup, TCP handshake, TLS negotiation, and server processing time. Google's Core Web Vitals program classifies TTFB under 800ms as "good," between 800ms and 1800ms as "needs improvement," and above 1800ms as "poor." While TTFB isn't one of the three official Core Web Vitals, it's a diagnostic metric that directly feeds into Largest Contentful Paint (LCP). A slow TTFB makes it nearly impossible to hit the 2.5-second LCP threshold. We've seen this pattern on dozens of projects: fix TTFB first, and LCP often resolves itself. TTFB matters most for server-rendered pages, API-dependent routes, and any origin that isn't sitting behind a CDN cache.
How it works
TTFB is composed of several sequential phases:
- DNS resolution — Translating the hostname to an IP address.
- TCP connection — Establishing the transport-layer connection.
- TLS handshake — Negotiating encryption (HTTPS adds 1-2 round trips unless TLS 1.3 is used).
- Request travel time — Network latency from client to server.
- Server processing — The time your application actually spends generating the response (database queries, SSR rendering, middleware execution).
- Response travel time — First byte traveling back to the client.
You can measure TTFB with the PerformanceNavigationTiming API:
const [entry] = performance.getEntriesByType('navigation');
const ttfb = entry.responseStart - entry.startTime;
console.log(`TTFB: ${ttfb.toFixed(0)}ms`);
In the field, Chrome User Experience Report (CrUX) records TTFB at the 75th percentile. Lighthouse (v12+) also surfaces it in its performance audit. Server-side, you can isolate server processing time from network time by comparing responseStart - requestStart against the total TTFB.
The biggest controllable factor is server processing. A Next.js page using getServerSideProps with an unoptimized Postgres query can easily add 300-500ms. Moving that query behind a Redis cache or switching to ISR (Incremental Static Regeneration) can drop server processing to under 10ms for cached paths.
When to use it
TTFB is the first metric to check when diagnosing slow page loads. It tells you whether the problem is on your server or in the browser.
Focus on TTFB when:
- LCP is above 2.5s and you suspect server-side delays
- You're running server-rendered (SSR) pages in Next.js or Astro SSR mode
- Your origin server is in a single region but your audience is global
- You've recently added middleware, auth checks, or database calls to the request path
- CrUX data shows TTFB above 800ms at p75
TTFB is less relevant when:
- Pages are fully static and served from a CDN edge (TTFB is usually <100ms already)
- Performance bottlenecks are client-side (heavy JavaScript, render-blocking resources)
- You're optimizing a single-page app where the initial document is a thin shell
Our preferred diagnostic flow: check TTFB first, then move to FCP and LCP. If TTFB is good and LCP is bad, the problem is in the browser. If TTFB is bad, don't bother optimizing anything else until you fix the server.
TTFB vs alternatives
| Metric | What it measures | Type | Good threshold |
|---|---|---|---|
| TTFB | Time until first response byte | Server + network | < 800ms |
| FCP | Time until first content is painted | Render | < 1.8s |
| LCP | Time until largest content element renders | Core Web Vital | < 2.5s |
| Server-Timing | Server-side processing breakdown | Diagnostic header | N/A (custom) |
TTFB overlaps with but isn't the same as "server response time." Server response time is only the processing phase; TTFB includes the full round-trip network cost. This distinction matters when your server is fast but your users are far away — that's a CDN problem, not a code problem.
Compared to LCP, TTFB is an upstream dependency. You can't have a fast LCP without a reasonable TTFB, but a fast TTFB doesn't guarantee a fast LCP (render-blocking CSS, lazy-loaded hero images, and client-side hydration can all add delay after the first byte arrives).
Real-world example
On a recent e-commerce project built with Next.js 14 App Router, our product detail pages had a p75 TTFB of 1,200ms. The culprit was a cascading set of API calls in a server component — product data, inventory check, and pricing all fetched sequentially.
We made three changes: parallelized the API calls with Promise.all, added a 60-second stale-while-revalidate cache header, and deployed to Vercel's edge network so the CDN could serve cached responses from 18+ PoPs. TTFB dropped to 180ms at p75. LCP followed, going from 3.4s to 1.9s. The page's CrUX assessment moved from "poor" to "good" within the next 28-day collection cycle.