TTFB (Time to First Byte) is the time between requesting a page and receiving the first byte of the server’s response. On WordPress, a high TTFB almost always comes from pages built without a cache, slow or overloaded PHP, heavy database queries or calls to external services. Fix it with server-side page caching first, then trim what WordPress runs on every uncached request.
Guide current as of 27 October 2026. Thresholds are those published by Google on web.dev; commands were tested with WP-CLI and curl.
Key takeaways
- Google rates TTFB as good up to 0.8 seconds and poor above 1.8 seconds. It is not a Core Web Vital, but it delays everything after it, starting with LCP.
- Test the same page twice in a row: the first request shows the cost of building it, the second shows whether the cache works.
- The number one cause is a missing or bypassed page cache: cookies, URL parameters or over-eager purges.
- For pages that cannot be cached (cart, account, admin), work on PHP, the database, plugins and external calls.
- Free tools pinpoint the slow part:
curl, the browser’s Network panel,wp profileand theServer-Timingheader.
What is TTFB, and why does it matter?
TTFB measures the time from the start of navigation until the first byte of the HTML page arrives. Until that byte lands, the browser cannot render anything or discover other resources, so every millisecond of TTFB is added straight onto Largest Contentful Paint (LCP), the moment your main content appears.
According to Google’s TTFB guide on web.dev, the figure is the sum of several phases, some of which have nothing to do with WordPress:
| Phase | What happens | Who controls it |
|---|---|---|
| Redirects | The browser follows each redirect (http to https, bare domain to www…) | You (settings, .htaccess, plugins) |
| DNS lookup | The domain name is resolved to an IP address | Your DNS provider |
| Connection and TLS | A TCP or QUIC connection opens and encryption is negotiated | Your host (TLS 1.3, HTTP/3) |
| Request processing | The server returns a cached page or runs PHP and database queries | Your host and your site |
| First byte | The start of the response travels back to the visitor | Distance and network quality |
The benchmarks are simple: 0.8 seconds or less is good, 0.8 to 1.8 seconds needs improvement, anything above is poor. Google calls these a rough guide; for WordPress, which returns a fully rendered HTML page, staying under 0.8 seconds is a sensible target.
How do you measure TTFB on a WordPress site?
Use three sources: PageSpeed Insights for real-visitor data, the browser’s Network panel for a specific page, and curl on the command line to break the time down and repeat the test. Always test logged out: administrators bypass the page cache.
1. Field data in PageSpeed Insights
For pages with enough traffic, PageSpeed Insights reports TTFB measured on real Chrome users over a rolling 28 days, mobile networks included. It moves slowly, so treat it as a trend rather than a way to validate today’s change. Our guide to Core Web Vitals on WordPress explains how to read the report.
2. The browser’s Network panel
Open a private window, open developer tools (F12), go to Network and reload. Click the first row (the HTML document) and open Timing: “Waiting for server response” is the time the server spent preparing the page, separate from DNS, connection and TLS. Under Headers, a LiteSpeed server adds x-litespeed-cache, which reads hit when the page came from the cache and miss when it was just generated.
3. curl, to break it down and repeat it
This command prints the cumulative time at each step. time_starttransfer is your TTFB; subtract time_appconnect to get the time the server spent building the response.
curl -s -o /dev/null -w "DNS : %{time_namelookup} s\nConnect : %{time_connect} s\nTLS : %{time_appconnect} s\nTTFB : %{time_starttransfer} s\nTotal : %{time_total} s\n" https://www.example.com/Run it two or three times, then check the cache status:
# First request: often "miss" (page built, then stored)
# Following requests: "hit" expected (served from cache)
curl -sI https://www.example.com/ | grep -i -E "x-litespeed-cache|cache-control|age"High TTFB despite a hit points to the network or the server. A big drop between miss and hit means caching works, and the job is to speed up pages that cannot be cached.
Network or server: where is your TTFB coming from?
If DNS, connection and TLS dominate, it is a network issue; if the wait after TLS dominates, it is the server or WordPress. Common symptoms and their likely causes:
| Symptom | Likely cause | How to check |
|---|---|---|
High TTFB even with x-litespeed-cache: hit | Network, DNS, overloaded or distant server | Compare DNS, connect and TLS times in curl |
High on miss, low on hit | Slow PHP page generation | Profile with wp profile or Query Monitor |
Always miss, or no cache header | Cache disabled or bypassed | Cache settings, cookies, URL parameters |
| Slow mostly in wp-admin | Autoloaded options, heavy plugins | Site Health, autoload size |
| Random slow spells | WP-Cron on page views, maxed-out resources | Scheduled task log, account resources |
| Time lost before the page even starts | Redirect chain | curl -sIL, count the 301/302 responses |
What causes high TTFB on WordPress?
Without a cache, every visit boots WordPress, loads the theme and plugins and runs dozens of SQL queries before a single byte goes out. Anything that slows that chain adds directly to TTFB:
- No cache, or a bypassed one: cookies that create variants, campaign parameters (
utm_,fbclid) treated as separate pages, full purges on every edit. - Old or saturated PHP: when every PHP worker is busy, new requests queue up.
- A cluttered database and expensive plugins: bloated autoloaded options, heavy queries run on every page.
- Avoidable waits: blocking external HTTP calls, WP-Cron running during visits, redirect chains, an undersized or distant server.
How do you reduce WordPress TTFB, step by step?
Work in order of payoff: page caching, then PHP and object caching, then database, plugins and external calls, then the network. Re-run the same curl command after each step.
1. Turn on server-side page caching
This is the single most effective fix: a cached page is returned without running PHP or touching the database. On a LiteSpeed server, the free LiteSpeed Cache plugin drives the cache built into the web server itself. Follow our LiteSpeed Cache setup guide, then confirm you see x-litespeed-cache: hit. On Apache or Nginx, pick one well-established caching plugin; our LiteSpeed vs Nginx vs Apache comparison explains the differences.
2. Serve more requests from the cache
Lengthen the public cache lifetime if your content rarely changes, purge only the affected pages when you publish instead of the whole cache, ignore campaign parameters in the cache key, and keep exclusions to genuinely personalised pages such as cart, checkout and account. If your host allows it, the LiteSpeed Cache crawler warms the cache before visitors arrive.
3. Run a supported PHP version
Each PHP release brings performance work, and only supported branches get security fixes. Per the official PHP support schedule, PHP 8.2 receives security fixes only until 31 December 2026, while 8.3, 8.4 and 8.5 are supported for longer. WordPress recommends PHP 8.3 or later. Test on a staging copy first; the active version is shown under Tools > Site Health > Info > Server.
4. Add an object cache for dynamic pages
Pages excluded from the page cache (WooCommerce cart, member areas, admin) hit the database every time. A persistent object cache such as Redis or Memcached keeps the results of repeated queries in memory. LiteSpeed Cache can connect to one under Cache > Object when your host provides the service. At Hosterwise, Redis is available on every plan: pick Redis as the method, enter the host and port shown in your customer area or given by support, save, then check that the Connection Test passes.
5. Slim down autoloaded options
On every request, WordPress loads all options flagged as “autoload” in one go, and uninstalled plugins often leave large ones behind. Since WordPress 6.6, Site Health flags a critical issue when their total size exceeds 800 KB, as explained in the WordPress core team’s developer note. If your host gives you SSH access, check the total and list the biggest offenders with WP-CLI (adjust the wp_ table prefix if yours differs):
# Total size of autoloaded options, in bytes
wp db query "SELECT SUM(LENGTH(option_value)) AS bytes FROM wp_options WHERE autoload IN ('yes','on','auto-on','auto');"
# The 10 largest autoloaded options
wp db query "SELECT option_name, LENGTH(option_value) AS bytes FROM wp_options WHERE autoload IN ('yes','on','auto-on','auto') ORDER BY bytes DESC LIMIT 10;"If a large option belongs to a plugin you removed, back up and delete it with wp option delete option_name. If it belongs to an active plugin, just stop autoloading it with wp option set-autoload option_name off and check the site still works. At Hosterwise, where there is no SSH access (a security choice), run the same two SELECT queries in the SQL tab of phpMyAdmin, opened from CyberPanel (Databases & FTP section); to delete an option or stop autoloading it, take a backup and ask our 24/7 support, who will run the command for you.
6. Profile WordPress to find the guilty plugin
The wp profile command, an official WP-CLI package (usable with SSH access), times each loading stage (bootstrap, main query, template) and then every callback attached to a hook. It runs uncached, which is exactly the cost of a generated page:
# Install the package once
wp package install wp-cli/profile-command:@stable
# Time per stage for a given URL
wp profile stage --url=https://www.example.com/blog/
# Drill into the slowest stage, hiding near-zero values
wp profile stage bootstrap --spotlight --url=https://www.example.com/blog/
# Most expensive callbacks on a specific hook
wp profile hook init --spotlight --url=https://www.example.com/blog/In the browser, the Query Monitor plugin complements this by listing slow and duplicate SQL queries per plugin; see our guide to diagnosing a slow WordPress site with Query Monitor. Without SSH access, as at Hosterwise, it is the tool to reach for first; our 24/7 support can also run wp profile for you.
7. Remove blocking external calls
A plugin that calls a remote API while the page is being built makes the visitor wait as long as that service takes to answer. Spot these calls (Query Monitor lists them under “HTTP API Calls”), then ask the plugin author to cache them, replace the plugin, or move the call into a scheduled task.
8. Hand WP-Cron over to the server
By default, WordPress checks its scheduled tasks during page views. Disable that with define( 'DISABLE_WP_CRON', true ); in wp-config.php and add a server cron job every five minutes from your hosting panel (at Hosterwise, the Cron Jobs section of CyberPanel). The full procedure is in our guide to speeding up WordPress in 15 steps.
9. Collapse redirect chains
Every redirect costs a full round trip before the page. A visitor typing http://example.com should hit one redirect only, straight to the final https address:
# Shows every response in the chain: expect a single 301
curl -sIL http://example.com/ | grep -i -E "^HTTP|^location"10. Tune the network: DNS, TLS 1.3, HTTP/3 and distance
Fast DNS shortens the lookup, TLS 1.3 cuts the encryption handshake to one round trip, and HTTP/3 (QUIC) merges connection and encryption setup while coping better with packet loss on mobile. Then there is distance: a server close to most of your visitors shortens every round trip, and for a global audience a CDN that caches HTML near visitors becomes worthwhile.
How can Server-Timing show where server time goes?
The Server-Timing HTTP header lets the server send its own measurements to the browser, which displays them in the developer tools’ Timing tab. You see network time and WordPress time side by side, with no extra tooling.
This small must-use plugin, saved in wp-content/mu-plugins/, adds two metrics for administrators only: the time WordPress took to boot and run the main query, and the number of SQL queries so far. As MDN points out, such data can help an attacker, so never expose it publicly.
<?php
/**
* Plugin Name: Server-Timing (administrators)
* Adds a Server-Timing header visible in browser developer tools.
*/
add_action(
'template_redirect',
static function () {
if ( headers_sent() || ! current_user_can( 'manage_options' ) ) {
return;
}
global $wpdb;
header(
sprintf(
'Server-Timing: wp;desc="bootstrap+query";dur=%.1f, sql;desc="%d queries"',
timer_float() * 1000,
(int) $wpdb->num_queries
)
);
},
PHP_INT_MAX
);Logged-in administrators bypass the page cache, so the figure reflects a freshly generated page. If wp accounts for most of the TTFB, the bottleneck is PHP and the database; if not, look at the template, the network or the server. Remove the plugin once you are done.
What TTFB should you aim for on each type of page?
Cached pages depend mostly on the network; personalised pages on PHP and the database.
| Page type | Cached? | What drives TTFB | Main lever |
|---|---|---|---|
| Home, posts, service pages | Yes | Network (DNS, connection, distance) | Cache hit rate, HTTP/3, proximity |
| Shop and product pages | Usually | Network, then rebuilds after purges | Targeted purges, cache warm-up |
| Cart, checkout, account | No | PHP, database, plugins | Recent PHP, object cache, fewer plugins |
| Site search, filters | Rarely | SQL queries | Indexes, lighter queries |
| Admin | No | Autoloaded options, plugins, external calls | Clean-up, profiling |
Checklist: cutting WordPress TTFB
- Measure three typical pages, logged out, with curl (two runs each) and write the numbers down.
- Check the cache header goes from
misstohit; set up targeted purges. - Move to PHP 8.3 or later after testing on staging.
- Enable an object cache if the site has dynamic pages.
- Check autoloaded options (warning at 800 KB).
- Profile with
wp profileor Query Monitor and deal with the most expensive plugin. - Remove blocking external calls, move WP-Cron to the server, shorten redirects.
- Confirm TLS 1.3 and HTTP/3, then measure again.
LiteSpeed hosting for a low TTFB from day one
Steps 1 to 4 and 10 depend heavily on your host. At Hosterwise, every plan runs on LiteSpeed Enterprise servers with the built-in LSCache page cache, a Redis object cache, HTTP/3 and free SSL certificates, so cached pages are served directly by the web server. Explore our LiteSpeed WordPress hosting or compare Starter, Premium and Boost on the pricing page. Hosted elsewhere? Our team moves your site for you with free migration.
WordPress TTFB: frequently asked questions
What is a good TTFB for WordPress?
Google rates 0.8 seconds or less as good and anything over 1.8 seconds as poor. For a page served from a server-side cache, processing is near-instant and TTFB mostly reflects the network. For a generated page, staying under 0.8 seconds takes a recent PHP version and well-behaved plugins.
Does TTFB affect SEO?
Indirectly. TTFB is not one of the Core Web Vitals, but it delays the main content and therefore LCP, which is. A slow server can also limit how many pages crawlers fetch in a given time.
Why is my TTFB fine for me but poor in PageSpeed Insights?
Your own tests usually hit an already cached page over a fast fixed connection. Field data includes mobile visitors, people further from the server and uncached pages.
Will a CDN fix a high TTFB?
Only if it caches HTML pages, not just images, CSS and JavaScript. A CDN that forwards every HTML request to your server only trims connection time. Start with server-side page caching; a CDN pays off for distant audiences.
Why is TTFB slower when I am logged in?
Logged-in users bypass the public page cache, so every page is built just for you, admin bar included. To measure what visitors get, test in a private window or with curl, without a session cookie.
Can switching hosts lower TTFB?
Yes, when the server is the bottleneck: high TTFB even on cached pages, outdated PHP, no server-side cache or maxed-out resources. If your cached TTFB is already low and only generated pages are slow, optimise the site itself first.

