High TTFB: How to Tell a Slow Server From a Slow Page in One curl Command

Hero image for High TTFB: How to Tell a Slow Server From a Slow Page in One curl Command
PC Drama
4 views

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.

Picture 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.

Phasecurl variableWhat it measuresWho owns it
Redirectstime_redirectEvery hop before the final URL, lookups and connections includedYour site's redirect rules
DNS lookuptime_namelookupTurning the domain name into an IP addressYour DNS host
TCP connecttime_connectOne round trip to the server or the CDN edgeDistance, so a CDN
TLS handshaketime_appconnectThe certificate exchange, one or two more round tripsThe TLS version on the origin or the edge
Server waittime_starttransfer minus time_pretransferThe request's trip out, the server's work, and the first byte's trip backYour 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.

Four translucent glass segments joined into one bar, the last and longest glowing green, with a thin bright vertical line crossing the bar as a threshold marker
Four phases, one bar, one line: the long segment at the end is the server wait, and the line is 800 milliseconds.

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
Open laptop on a dark desk at night showing a terminal window of blurred amber glyphs, with a coiled ethernet cable beside it
Five numbers on one line, read left to right, in the order the browser waits for them.

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.

Expert Tip: Make the Server Confess Its Own Split

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 Origin

We 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.

VariantDNSTCP connectTLS doneFirst byteServer wait
Through the edge, cache miss (n=10)4 ms41 ms86 ms307 ms226 ms
Straight to the origin, cache miss (n=10)0 ms19 ms48 ms166 ms107 ms
Straight to the origin, plain URL (n=5)0 ms31 ms59 ms171 ms107 ms
Through the edge, cache hit (n=5)4 ms43 ms85 ms122 ms34 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
A glowing violet root node branching into four luminous paths that each end at a small frosted glass block, floating over a dark grid
Four branches, four owners: the DNS host, the network, the TLS configuration and the box itself.

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.

PatternLikely causeThe fix
DNS over 100 ms on repeat runsA slow or distant DNS hostMove DNS to a fast anycast provider and check the record's TTL
TCP connect over 100 msThe server is far from the visitorA CDN in front, or a host in the region your customers live in
TLS adds more than the connect tookAn old TLS version or no session resumptionTLS 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 stringThe cache works and the origin is slow underneathFix the origin anyway, because every cache miss pays the full price
Server wait large on bothNo page cache, or a crowded hostPage caching first, then OPcache and query work, then the plan
Server wait swings by hourShared hosting at capacityMeasure at noon and at 3 a.m.; if they differ by seconds, move
Redirect time above zerohttp to https, www hops, trailing slashesOne hop at most, and HSTS so browsers skip the http hop
A glowing emerald contour map rising into one tall ridge in the centre over a dark grid, like a load graph with a single busy hour
A crowded host draws this shape over a day: flat at 3 a.m., a ridge at lunch.

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
VariableWhat curl measures, from the start of the requestPhase it closes
time_redirectAll redirection steps, including their own lookups, connects and transfers, before the final request startedRedirects
time_namelookupUntil name resolving was completedDNS lookup
time_connectUntil the TCP connect to the remote host or proxy was completedTCP connect
time_appconnectUntil the SSL or SSH handshake to the remote host was completedTLS handshake
time_pretransferUntil the file transfer was just about to begin, after every protocol-specific negotiationRequest ready
time_starttransferUntil the first byte is received, which includes time_pretransfer plus the time the server needed to calculate the resultServer wait, and TTFB
time_totalUntil the full operation finishedContent 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.

The Chrome team defines TTFB on web.dev and in DevTools; the thresholds come from the HTTP Archive's Web Almanac.

Run 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.

Related Articles