Performance
TTFB: what it measures and how to cut it
TTFB is the time from request to first byte. On our site the median is 350 ms, 59 ms of it handshake: how to measure it and what cuts it.
Key points
- Measure TTFB with curl or the Navigation Timing API, never with Lighthouse alone.
- Google's threshold is 800 ms at the 75th percentile; above 1,800 ms the page needs work.
- On our site the cold-connection median is 350 ms, and 59 ms of that is handshake.
- When TTFB is good and LCP is high, the bottleneck is rendering, not the server.
TTFB (time to first byte) is the time between the browser request and the first byte of the response: under 800 ms is good, above 1,800 ms needs work. It measures server and network, not rendering.
The four parts of TTFB
| Phase | What causes it | Where to read it | Remedy |
|---|---|---|---|
| DNS | Domain resolution | domainLookupEnd - startTime | dns-prefetch and a higher TTL |
| TCP and TLS | Handshake with the origin | connectEnd and secureConnectionStart | keep-alive, HTTP/2, preconnect |
| Server | Queue, query, cold start | responseStart - requestStart | HTML cache, indexes, edge |
| Transfer | First byte after the response | responseStart | compression and shorter HTML |
On our site the server weighs more than the handshake: 291 ms against 59 ms. That is normal when the HTML is generated on every request and no cache reuses it.
Measuring it from a terminal
for i in $(seq 1 20); do curl -s -o /dev/null -w "%{time_starttransfer}\n" https://example.com/; done | sort -n
The command needs bash, curl and a connection. The time_starttransfer field includes handshake and transfer: for the server time alone read time_pretransfer as well and subtract.
What cuts TTFB
- Cache: answer the HTML from cache when it does not change, and drop duplicate queries on the same page. Source: web.dev, CC BY 4.0.
- Connection: keep the socket open with keep-alive and HTTP/2 to the same origin.
- External origins: add rel=preconnect only for the hosts you really use. Source: MDN, CC BY-SA 2.5.
- Distance: when the audience is far from the server, put an edge cache in front of the origin.
The limitation to name
TTFB says nothing about rendering: a page with 300 ms of first byte and 4 s of LCP has the problem in JavaScript, not in the server. It is not a Core Web Vital either, it is a diagnostic metric, and you read it next to LCP, INP and CLS.
Where to continue
The EneUI catalogue indexes 111,985 components, 1,556 blocks and the record hero parallax: a hero with many images inflates the HTML and stretches the first byte. For the thresholds read what Core Web Vitals are, for rendering what makes LCP worse, and for the comparison of architectures frontend frameworks compared.
Frequently asked questions
Is TTFB a Core Web Vital?
No. It is a diagnostic metric: Google reports it next to LCP, INP and CLS, but it does not enter the Core Web Vitals score.
What is an acceptable threshold?
Under 800 ms at the 75th percentile is good, above 1,800 ms needs work. Under 500 ms you keep room for mobile networks.
Why is the TTFB I measure different from Search Console?
Search Console uses 28 days of field data from real users; curl measures one request from your network. Latency, cache and location change the number.
Does Lighthouse show TTFB?
Yes, the server-response-time audit reports lab TTFB from a single run. Field data decides whether the page passes.
What cuts TTFB without changing hosting?
An HTML cache, indexes on queries, fewer synchronous calls on the critical path and keep-alive. When the server is far from the audience you need an edge or another region.