Time to First Byte (TTFB) — measuring and improving server response
TTFB = time from navigation request to first byte of response. Target: < 200ms cached, < 600ms uncached. Drivers: DNS, TCP/TLS, server response time, redirect chain. Fix: CDN edge caching, geographically close origin, HTTP/2/3, reduce origin work (caching layer, async work moved off the critical path), eliminate redirects, persistent connections.
TTFB is the time from "user hit Enter" to "first byte arrives" — the pre-render latency the browser can't do anything about. Fixing it improves every downstream metric (FCP, LCP, INP).
What's in TTFB
TTFB = DNS + TCP + TLS + Request + Server processing + Initial response transitEach segment is a target.
Targets
- < 200ms when cached at the CDN.
- < 600ms for uncached / dynamic responses.
- > 1000ms is a serious problem.
Measured at p75 — averages hide tail latency.
Drivers of TTFB
DNS lookup
Cold lookups take 20–100ms. Mitigations:
<link rel="dns-prefetch">for third-party origins.- Long DNS TTLs.
TCP + TLS handshake
100–300ms cold. Mitigations:
- HTTP/2 multiplexing (one connection serves many requests).
- HTTP/3 (QUIC) — 0-RTT resumption.
- TLS session resumption.
- Persistent connections.
Server processing
The biggest variable. Drivers:
- DB queries (especially N+1).
- External API calls in the request path.
- Heavy template rendering.
- Cold-starts (serverless).
Redirects
Each redirect adds an entire round trip + handshake. Eliminate or collapse.
Network distance
If origin is in us-east and user is in Singapore, base RTT is 200ms+. Edge caching is the answer.
Fixes
1. CDN edge caching
The biggest single win. Cache static assets (immutable, hashed) forever; cache HTML where possible (with smart invalidation):
Cache-Control: public, max-age=86400, stale-while-revalidate=600- ISR (Next.js) / per-route caching.
- Personalized content — use ESI/edge personalization or split static shell from dynamic data.
2. Get the origin closer
- Multi-region deployment.
- Edge runtime for the API layer (Vercel Edge, Cloudflare Workers).
- Geographically routed DNS (Anycast).
3. Reduce origin work
- Cache DB results (Redis).
- Eliminate N+1 queries.
- Avoid synchronous external calls in the request path — push to background jobs.
- Don't compute on render what you can compute on write.
4. HTTP/2 or HTTP/3
Multiplexing, header compression, 0-RTT resumption. Free wins if your stack supports them.
5. Eliminate redirects
- HTTP → HTTPS via HSTS preload (one redirect saved on first visit, none after).
- www ↔ non-www: pick one canonical.
- Trailing slash policy: pick one.
6. Compression
Brotli for text — smaller than gzip; supported by all modern browsers.
7. Persistent connections
Keep-Alive is default in HTTP/1.1; HTTP/2 multiplexes. Don't kill it inadvertently.
How to measure
- Navigation Timing API:
const nav = performance.getEntriesByType("navigation")[0];
const ttfb = nav.responseStart - nav.requestStart;- web-vitals library:
import { onTTFB } from "web-vitals";
onTTFB((m) => send(m));- Server logs for the server-processing portion.
- WebPageTest for waterfall view per region/device.
TTFB in the funnel
TTFB is the floor for FCP. If TTFB is 800ms, FCP can never be under 800ms. Fixing TTFB lifts every downstream paint metric.
Interview framing
"TTFB is DNS + TCP + TLS + server processing + first-byte transit. Target < 200ms cached, < 600ms uncached. The biggest single lever is a CDN with aggressive edge caching — static assets immutable + hashed, HTML cacheable where possible with ISR or stale-while-revalidate for dynamic pages. Beyond caching: get origin closer (multi-region, edge runtime), reduce origin work (cache DB results, eliminate N+1, push non-critical work off the request path), use HTTP/2 or 3 for multiplexing and 0-RTT resumption, and eliminate redirects. Measure with the Navigation Timing API and the web-vitals library at p75. TTFB is the floor for FCP, so fixing it lifts every downstream paint metric."
Follow-up questions
- •Why is TTFB the floor for FCP?
- •How does HTTP/2 reduce TTFB on warm connections?
- •What's stale-while-revalidate and when is it appropriate?
- •How do you handle TTFB for authenticated, personalized pages?
Common mistakes
- •Optimizing FCP/LCP without first fixing TTFB.
- •Computing on render what could be computed on write.
- •Long redirect chains (especially HTTP→HTTPS→www→canonical).
- •Synchronous third-party API calls in the request path.
Performance considerations
- •Edge caching is the dominant lever. Origin work and redirects are next. HTTP/2/3 + Brotli are free wins.
Edge cases
- •Cold-start TTFB on serverless — first request after idle.
- •Personalized pages that can't cache at the CDN.
- •API workloads vs HTML — different caching strategies.
Real-world examples
- •Vercel + Next.js ISR; Cloudflare Workers; AWS CloudFront + Lambda@Edge.