Part of the Why Is My Website Slow? How to Find the Cause in 15 Minutes. Start there for the wide view, then come back here for the close-up.
High TTFB Is a Wait With Four Parts
Link to section: High TTFB Is a Wait With Four PartsPicture the PageSpeed report open on a second monitor: "Reduce initial server response time", 1.2 seconds, in orange. Three people have already offered to fix it: the host with a bigger plan, the agency with a CDN, the caching plugin with its premium tier. Each would shrink a different slice of that 1.2 seconds, and the report does not say which slice you have.
This page is the close-up on a high TTFB: the four waits that add up to time to first byte, how to read each one off a single curl line, what that line found when we pointed it at our own origin, and a table that turns the slow phase into the person who can fix it.
| Phase | curl variable | What it measures | Who owns it |
|---|---|---|---|
| Redirects | time_redirect | Every hop before the final URL, lookups and connections included | Your site's redirect rules |
| DNS lookup | time_namelookup | Turning the domain name into an IP address | Your DNS host |
| TCP connect | time_connect | One round trip to the server or the CDN edge | Distance, so a CDN |
| TLS handshake | time_appconnect | The certificate exchange, one or two more round trips | The TLS version on the origin or the edge |
| Server wait | time_starttransfer minus time_pretransfer | The request's trip out, the server's work, and the first byte's trip back | Your host, your application, your cache |
Each curl value is a running total from the start of the request, so a phase is the difference between neighbouring numbers, and the fourth number is the TTFB that Chrome reports. The wait row is the only one a hosting plan can change, and the report lumps it in with the other three.
What Counts as a High TTFB?
Link to section: What Counts as a High TTFB?
A TTFB over 800 milliseconds is high by the HTTP Archive's line, and Lighthouse complains sooner: its server response audit fails when the browser waits more than 600 milliseconds for the main document. One number comes from real visitors and one from a single simulated load, so a site can fail the audit on every run and still pass in the field, or the reverse.
Most sites miss the softer line. The 2024 Web Almanac found 42% of mobile sites with a good TTFB, 40% in the needs-improvement band and 19% poor. Chrome's own definition of the waiting phase explains why no image compressor can touch any of them: "This timing includes 1 round trip of latency and the time the server took to prepare the response."
How to Measure TTFB With One curl Line
Link to section: How to Measure TTFB With One curl Line
Run this against your home page:
curl -o /dev/null -s -w '%{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{http_code}\n' https://example.com/
Run it ten times and keep the middle value, since one request can catch a cold DNS cache and tell a story that is true once. The first number is DNS, the second adds the TCP connect, the third adds TLS, and the fourth is the first byte. Subtract the third from the fourth and you have the server wait, the only number worth arguing about with your host.
Two variations do most of the diagnosis. Add a throwaway query string such as ?nocache=4821 to force a cache miss, so you compare the page your CDN serves with the page your origin builds. Then bypass the CDN with --resolve example.com:443:203.0.113.10, which opens the connection to that IP while still sending the real hostname and checking the real certificate.
From the outside the server wait is a black box: the request's trip, the application's work and the reply's trip, blended. A Server-Timing response header opens it. One line such as Server-Timing: db;dur=53, app;dur=120 shows up in Chrome's Network panel under the Timing tab, so you can see whether the database or the template took the time. Emit it from the origin, not the CDN.
What One curl Line Found on Our Own Origin
Link to section: What One curl Line Found on Our Own OriginWe timed this cluster's hub page ten ways on the night of October 1, 2026, and the server turned out to own about a third of the wait. A cache-missing request through Cloudflare's edge returned its first byte in a median 307 milliseconds. The same request sent straight to the origin, with the edge bypassed by --resolve, took a median 166 milliseconds, and the origin's own wait, first byte minus the end of the TLS handshake, was a median 107 milliseconds.
How we measured: 10 curl requests per variant to /blog/why-is-my-website-slow from a machine in the Dallas area between 11:53 pm and 11:55 pm Central on October 1, 2026, each with a unique ?nocache= query string so every request missed the edge cache (cf-cache-status: MISS on all 10), reading time_namelookup, time_connect, time_appconnect, time_pretransfer and time_starttransfer. Medians shown. Five further requests per variant without the query string gave the plain-origin and warm-edge rows.
| Variant | DNS | TCP connect | TLS done | First byte | Server wait |
|---|---|---|---|---|---|
| Through the edge, cache miss (n=10) | 4 ms | 41 ms | 86 ms | 307 ms | 226 ms |
| Straight to the origin, cache miss (n=10) | 0 ms | 19 ms | 48 ms | 166 ms | 107 ms |
| Straight to the origin, plain URL (n=5) | 0 ms | 31 ms | 59 ms | 171 ms | 107 ms |
| Through the edge, cache hit (n=5) | 4 ms | 43 ms | 85 ms | 122 ms | 34 ms |
Two things surprised us. We expected the edge to add one round trip to the origin on a miss, around 20 milliseconds, and it added 141, so a visitor who misses the cache pays nearly twice what the origin alone charges. And the plain and cache-busting URLs cost the origin the same 107 milliseconds, because our application stores the rendered page under the post's slug and ignores the query string, so the "uncached" test was timing a framework boot and a cache read rather than a page build. Take one round trip off that wait, the 19 millisecond TCP connect, and the origin's own work comes out near 90 milliseconds per page. One request in ten, the first, took 1.03 seconds before anything on the path had warmed up, the number a ten-run median hides.
We measured this on our own site: the server itself spends about a tenth of a second on each page, so a bigger server could never have made it much faster, and the cache in front of it is where the speed comes from.
Which Phase Is Slow, and Who Fixes It
Link to section: Which Phase Is Slow, and Who Fixes It
Read the ten-run medians, find the phase that is out of proportion, and the table names the fix. The same 900 milliseconds can be a slow resolver, a server across an ocean, or a PHP process rebuilding the page for every visitor.
| Pattern | Likely cause | The fix |
|---|---|---|
| DNS over 100 ms on repeat runs | A slow or distant DNS host | Move DNS to a fast anycast provider and check the record's TTL |
| TCP connect over 100 ms | The server is far from the visitor | A CDN in front, or a host in the region your customers live in |
| TLS adds more than the connect took | An old TLS version or no session resumption | TLS 1.3 and HTTP/2 on the origin, or let the CDN terminate TLS |
| Server wait small on the plain URL, large with a query string | The cache works and the origin is slow underneath | Fix the origin anyway, because every cache miss pays the full price |
| Server wait large on both | No page cache, or a crowded host | Page caching first, then OPcache and query work, then the plan |
| Server wait swings by hour | Shared hosting at capacity | Measure at noon and at 3 a.m.; if they differ by seconds, move |
| Redirect time above zero | http to https, www hops, trailing slashes | One hop at most, and HSTS so browsers skip the http hop |
Three Signs the Host Is the Problem
Link to section: Three Signs the Host Is the Problem
Shared hosting earns its reputation one lunch hour at a time, and the signs are consistent. The uncached, direct-to-origin wait runs past a second, it is worse at the busy hours than at 3 a.m., and the admin dashboard, which no page cache ever helps, drags too.
"While a good TTFB doesn't necessarily mean you will have a fast website, a bad TTFB almost certainly guarantees a slow one."
Harry Roberts Consultant web performance engineer, CSS Wizardry, in Time to First Byte: What It Is and Why It Matters
Lighthouse's fix list for a failed server response audit reads in the order worth trying: application logic, database queries, memory or CPU, then a CDN for network latency. Google's TTFB guidance lists caching right after hosting and a CDN, noting that "even a short caching time can result in noticeable performance gains", because a page cache turns a 900 millisecond PHP render into a file read for every visitor who is not logged in. If the direct-to-origin wait still runs past a second with caching on, the host is out of headroom, and if it drops under 200 milliseconds you have saved the cost of a migration.
The curl -w Variables: One Line Each, From the Manual
| Variable | What curl measures, from the start of the request | Phase it closes |
|---|---|---|
time_redirect | All redirection steps, including their own lookups, connects and transfers, before the final request started | Redirects |
time_namelookup | Until name resolving was completed | DNS lookup |
time_connect | Until the TCP connect to the remote host or proxy was completed | TCP connect |
time_appconnect | Until the SSL or SSH handshake to the remote host was completed | TLS handshake |
time_pretransfer | Until the file transfer was just about to begin, after every protocol-specific negotiation | Request ready |
time_starttransfer | Until the first byte is received, which includes time_pretransfer plus the time the server needed to calculate the result | Server wait, and TTFB |
time_total | Until the full operation finished | Content download |
Chrome's Network panel shows the same phases under different names: DNS Lookup, Initial connection (which folds TCP and SSL together), Request sent, and Waiting (TTFB), followed by Content Download. Queueing and Stalled sit in front of them in the browser and have no curl equivalent, which is one reason curl's number is usually a little smaller than Chrome's.
Google's TTFB Fix List, Mapped to the Phase Each One Shortens
- Hosting with enough memory and a current backend stack. Shortens the server wait. The only item on the list that costs a monthly fee, and the one most people buy first.
- A CDN with HTTP/2 or HTTP/3, fast DNS and TLS 1.3. Shortens TCP connect and TLS by moving both close to the visitor, and shortens the server wait on every cache hit.
- Cache-Control headers. Shorten the server wait for everyone who hits the cache; Google notes that even a short caching time pays.
- No same-origin redirects, and HSTS for the http hop. Removes the redirect phase entirely, since each hop repeats the lookups and connections before it.
- Streaming the markup instead of holding it until the whole page is built. Moves the first byte earlier without making the server any faster.
- A service worker with a stale-while-revalidate strategy for repeat visitors. Replaces the whole network wait on a return visit.
- 103 Early Hints. Lets the browser start fetching render-critical files while the server is still preparing the HTML, so the wait overlaps with useful work.
TTFB Questions a Hosting Upgrade Will Not Answer
- Why does curl report a faster TTFB than Chrome does?
- Because curl starts its clock at the request and skips what the browser does before it: queueing behind higher-priority requests, the six-connection limit per origin, service worker startup, and disk cache allocation. Chrome's Waiting phase also runs on a phone over a mobile network for most of your visitors, while curl runs from a desk. Use curl to split the phases and Chrome's field data to know what visitors actually feel.
- Can a CDN make TTFB worse?
- On a cache miss, yes. The edge has to fetch the page from the origin before it can answer, and on our own site that miss cost 141 milliseconds more than going to the origin directly. The CDN earns its keep on the hits, so check the cache hit ratio in its dashboard before judging it by a single uncached test.
- Does a high TTFB matter if my LCP already passes?
- Less, in the short term, because Google scores LCP and not TTFB. It still matters as an early warning: TTFB is the floor under every other metric, so a first byte that creeps from 300 to 700 milliseconds over a year will eventually push LCP over the line without any front-end change to blame.
- What is a good TTFB for a WordPress site?
- The lines do not change by platform: under 800 milliseconds in the field and under 600 in Lighthouse. What changes is how you get there. An uncached WordPress page runs PHP and a stack of database queries per visit, so page caching is the first fix and usually the biggest, and the server wait with caching on is the number to compare against a host's promises.
About Time to First Byte
Link to section: About Time to First Byte- HTTP Archive: Web Almanac 2024, Performance chapter
- Chrome DevTools: Network reference, timing phases
- Lighthouse: Reduce server response times
- web.dev: Optimize Time to First Byte
- curl manual: --write-out and --resolve
- MDN: Server-Timing header
The Chrome team defines TTFB on web.dev and in DevTools; the thresholds come from the HTTP Archive's Web Almanac.
Before You Buy the Bigger Server
Link to section: Before You Buy the Bigger ServerRun the line ten times, cached and uncached, through the CDN and straight to the origin, and put the medians in a row before anyone quotes you a price. If the server wait is the big slice and stays big with caching on, the host has earned the invoice. If the big slice is DNS, distance or TLS, the server was never the problem, and the wider checklist of reasons why your website is slow walks the rest of the page in fifteen minutes. The PageSpeed Scanner runs the lab version of this check on any site and keeps the number so you can watch it move.
Sources: HTTP Archive, Web Almanac 2024: Performance; Chrome for Developers, Lighthouse: Reduce server response times; Chrome for Developers, Network features reference; web.dev, Optimize Time to First Byte; curl, the curl manual page; MDN, Server-Timing; Harry Roberts, Time to First Byte: What It Is and Why It Matters.