TTFB (Time To First Byte)
TTFB is the time from the start of a request until the first byte of the response arrives. It contains redirects, DNS, connection, TLS and the server's work, so it is not page-load time and not a Core Web Vital. web.dev's rough guide: 0.8s or less is good, over 1.8s poor.
Full Explanation
Time To First Byte (TTFB) is the time from the start of a request until the first byte of the response begins to arrive. It bundles every step that has to finish before any content can be sent. These steps include redirects, service worker startup, DNS resolution, connection setup, the TLS negotiation, and the server's own work. It is not total page-load time. The clock stops at the first byte, not the last. Almost everything that decides how fast a page feels happens afterwards. Cloudflare's own summary is the honest one: TTFB is a great signal for connection setup time, server time, and network latency. It is a weak signal for how a page loads in a browser. It is a diagnostic metric, not one of the three Core Web Vitals.
How it works
web.dev defines TTFB as the sum of the request phases that run before the response, in order:
- Redirect time. Every hop in a redirect chain sits inside TTFB. That is why a stray http-to-https or www hop shows up as a slow server.
- Service worker startup time, where a service worker is registered.
- DNS lookup: turning the hostname into an address.
- Connection setup and the TLS negotiation, each step priced in round-trip times.
- The request itself, up to the point when the first byte of the response arrives. The server's processing time lives in this phase.
Two readings dominate in practice. In the browser, TTFB is the navigation entry's responseStart, measured from the start of the navigation. curl reports the same idea as %{time_starttransfer}. Its manual defines this as the time from the start until the first byte was received, including time_pretransfer and the time the server needed to calculate the result. Neither number isolates the server. Both still carry DNS, connection, and TLS.
"First byte" is not a fixed point either. A 103 Early Hints interim response counts as the first bytes, so responseStart stops there. A separate finalResponseHeadersStart entry marks the start of the final document response. Flushing document headers early has the same effect. A TTFB figure is therefore only comparable against the same tool, the same definition of first byte, and the same measurement point in the network.
Why it matters for a CDN
A cache hit is the cheapest TTFB there is: the edge answers the request and never reaches the origin. Origin time therefore leaves the number altogether. Cloudflare's edge-side field for it reads 0 when the request was served from cache and the origin was not reached. On a miss, TTFB grows by the network round trip from the edge to the origin, plus the time the origin spent handling the request. So origin placement, the routing path, and origin processing decide the miss figure. That makes TTFB the natural first split in CDN work: hits test the edge and the client's network, misses test the origin path.
Because nothing can render before a byte arrives, TTFB gates everything downstream. web.dev's rough guide is 0.8 seconds or less as good and above 1.8 seconds as poor. This guide is framed as responding fast enough to keep the 75th percentile of users inside a good First Contentful Paint result. It is not a pass or fail for the site. The ceiling is real, though. TTFB is one of the sub-parts of Largest Contentful Paint. Yet in four samples of 200,000 page views from Cloudflare's real user monitoring data, about 21% of page views with a good TTFB still did not have a good LCP.
What CDNs do
CDNs measure TTFB at the edge and expose it as a field you can log, alert on and match rules against.
- Cloudflare exposes cf.timings.origin_ttfb_msec in its rules language. This is the Time to First Byte from the perspective of the Cloudflare edge server. It includes both the network RTT and the time the origin server spent handling the request. It reads 0 when the request was served from cache and the origin was not reached. Rules can match on it directly, for example origin TTFB above 2 seconds.
- Fastly exposes the read-only VCL variable time.to_first_byte. This is the time interval since the request started up to the point before vcl_deliver ran. It is available in the deliver and log phases. In vcl_log, the difference between time.elapsed and time.to_first_byte is the time it took to send the response body. That is exactly the part TTFB does not measure.
Both are edge-side numbers. They report what the CDN saw, not what the browser saw. So they sit alongside real-user data rather than replacing it.
Watch out for
- TTFB is not a Core Web Vital. The three Core Web Vitals are Largest Contentful Paint, Interaction to Next Paint and Cumulative Layout Shift. TTFB is a diagnostic that supports them. Treating it as the vital is how a site ends up with a fast first byte and a slow page.
- Lower is not automatically better. Early Hints stops the TTFB clock sooner. Turning it on at the edge improves the number without the origin getting any faster. Compression at the origin runs the other way. It raises TTFB while the page still loads faster overall.
- Server response time is not TTFB. Lighthouse's server response time audit fails above 600 ms. That threshold sits deliberately below the 800 ms TTFB guide, because server response time excludes the redirects and DNS lookups that TTFB includes. As of Lighthouse 13, that audit has moved into the Document request latency insight.
- curl's %{time_starttransfer} includes the network journey, so it is not a server-only time. Cloudflare's timing guide estimates the server's share as TTFB minus roughly one network round trip. It approximates that round trip as time_connect minus time_namelookup. That is a better guess, not a measurement.
- TTFB stops at the first byte. So it is a fair verdict on a single small object, an API response, or a file download. It is a weak verdict on a whole page, whose render-blocking work all comes later.
- One read is not a verdict. TTFB moves with client location, the edge chosen, the routing path, and cache state. A single measurement hides all four.
Best practice
- Split a slow TTFB into its phases before changing anything: redirects, DNS, connect, TLS, then the server's answer. curl's timing variables give the whole breakdown from one request. That lets you fix the layer that is actually slow.
- Separate hits from misses. Confirm the cache state from the X-Cache or equivalent cache-status header instead of assuming it. A slow hit points at the client network, the edge chosen, or the TLS setup. A slow miss points at the edge-to-origin leg and the origin itself.
- Measure from several vantage points and report the 75th percentile. That is how the field thresholds are defined, so one noisy run does not decide.
- For miss-heavy traffic, shorten the edge-to-origin leg. Move the origin closer, or put an origin shield in front of it. That way, misses from many edges converge on one cache tier instead of each edge going to the origin.
- Pair TTFB with user-centric metrics from real visitors, First Contentful Paint and Largest Contentful Paint, before calling it the verdict on page speed. TTFB is where debugging starts, not where it stops.
Examples
# Measure TTFB with curl
$ curl -w 'TTFB: %{time_starttransfer}s\n' -o /dev/null -s https://cdn.example.com/
TTFB: 0.038s # 38ms - cache hit from local PoP
# Break down the components
$ curl -w 'DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\n' -o /dev/null -s https://cdn.example.com/
DNS: 0.004s
Connect: 0.008s
TLS: 0.015s
TTFB: 0.022s
# Compare cache hit vs miss
# HIT: TTFB ~20ms (served from edge)
# MISS: TTFB ~180ms (fetched from origin in another continent)
Frequently Asked Questions
TTFB is the time from the start of a request until the first byte of the response arrives. It contains redirects, DNS, connection, TLS and the server's work, so it is not page-load time and not a Core Web Vital. web.dev's rough guide: 0.8s or less is good, over 1.8s poor.
# Measure TTFB with curl
$ curl -w 'TTFB: %{time_starttransfer}s\n' -o /dev/null -s https://cdn.example.com/
TTFB: 0.038s # 38ms - cache hit from local PoP
# Break down the components
$ curl -w 'DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\n' -o /dev/null -s https://cdn.example.com/
DNS: 0.004s
Connect: 0.008s
TLS: 0.015s
TTFB: 0.022s
# Compare cache hit vs miss
# HIT: TTFB ~20ms (served from edge)
# MISS: TTFB ~180ms (fetched from origin in another continent)
Related CDN concepts include:
- Cache Hit Ratio (CHR) — The share of requests a cache answers from its own stored copies instead of fetching …
- Latency — Latency is the time data takes to travel from one point on a network to …
- RTT (Round-Trip Time) (RTT) — RTT (round-trip time) is the delay from sending a packet until the response it triggers …