Reduce server response time by measuring where the request waits, then fixing that part of the delivery path. A slow first byte can come from redirects, connection setup, a distant origin, application work, database queries or a cache miss. Changing hosting before separating those causes can move the same bottleneck to a more expensive server.
Time to First Byte, or TTFB, is the time until the browser receives the first response byte for the navigation. It is broader than the time your application spends generating HTML. The practical goal is to deliver useful content sooner, so always check the effect on rendering as well as on the first byte.
Define the measurement before choosing a target
Google's TTFB optimization guidance treats 800 milliseconds or less as a rough good target. TTFB is not itself one of the three Core Web Vitals. A value above that guidance deserves investigation, but the final judgment must include how quickly meaningful content appears.
A server-rendered page can spend longer preparing HTML and still display useful content before a client-rendered page that returns an empty shell immediately. That does not make slow application work desirable. It means a first-byte improvement achieved by postponing all useful work until JavaScript runs may be a poor trade.
Measurements also differ in scope. Navigation-level field TTFB can include delays that a lab audit of the final document excludes. The historical Lighthouse server-response-time audit did not represent the entire DNS, redirect and connection sequence. Current Chrome guidance also uses the Document request latency insight, so an old audit name in a tutorial may not match the report in front of you.
Write down which value you are optimizing: field navigation TTFB, the waiting portion in a browser request, an application timer or a command-line first-byte result. Comparing them as if they were interchangeable produces contradictory conclusions even when each measurement is correct.
Follow the request from navigation to useful HTML
Several stages can precede the first useful document response. Their costs depend on cached DNS, existing connections, redirects, protocol choices and the route through your delivery infrastructure.
| Stage | What can delay it | Evidence to inspect |
|---|---|---|
| Redirects | Multiple hostname, scheme or path changes | Status codes and redirect chain |
| DNS and connection setup | Resolver delay, distance, a fresh connection | Browser request timing |
| TLS negotiation | New secure connections and network round trips | Connection timing and reuse |
| Edge processing | Cache lookup, rules, origin fetch | CDN response headers and logs |
| Origin queue and execution | Busy workers, database work, external services | Application traces and server metrics |
| Response delivery | Buffering, distance and transfer behavior | First-byte timing and waterfall |
Do not assume every stage occurs on every request. A returning visitor may reuse a connection. A cache hit can avoid application execution. A request for a private account page should not reuse public HTML intended for someone else.
The most revealing comparison is often between two legitimate paths to the same content. A warm public page and an uncached page can have very different timings. That difference tells you which part of the system is currently protecting visitors from slow origin work.
Establish a browser baseline with the real visitor path
Open DevTools before navigating and inspect the document request in the Network panel. Record its final URL, status, protocol, response headers and timing breakdown. Keep redirects visible. A test that starts directly at the final destination cannot explain delays introduced by an earlier redirect from a campaign or outdated internal link.
Run separate cold and warm tests. Disabling the browser cache changes browser reuse; it does not necessarily bypass a CDN or a server-side page cache. Likewise, a private browsing window does not guarantee an empty edge cache. Identify the cache layer you are trying to control.
Test representative content. The homepage may be unusually popular and almost always cached, while older articles are generated on demand. Search results, account pages and checkout can take paths that public content never uses. Keep authenticated tests private and avoid placing session cookies in shared reports.
Repeat the test from regions that matter to your audience where you have a legitimate testing service or monitoring setup. One fast request from a machine close to the origin is weak evidence about visitors far away. Describe the location and conditions instead of presenting one measurement as a worldwide result.
Use curl to separate cumulative milestones
The following command performs a GET request, discards the body and prints cumulative timing milestones. Replace the example URL with a public page you are authorized to test. It intentionally does not follow redirects, so a redirect remains visible rather than silently changing the measured request.
curl --silent --show-error --output /dev/null \
--write-out 'status=%{http_code}\ndns=%{time_namelookup}\nconnect=%{time_connect}\ntls=%{time_appconnect}\nfirst_byte=%{time_starttransfer}\ntotal=%{time_total}\n' \
'https://example.com/'These values are elapsed times from the beginning of the transfer. Do not add them together. For a straightforward new HTTPS connection, differences between adjacent milestones can help isolate connection and TLS setup, but proxies, reuse and protocol behavior can change the interpretation.
The interval after connection setup and before the first byte is not a pure application timer. It includes network effects as well as server-side work. Use it to locate the likely region of the delay, then use server instrumentation to distinguish database execution, rendering and queueing.
Check the returned status before interpreting performance. A fast redirect, error page or bot challenge is not a fast successful page. Also avoid replacing GET with HEAD for convenience when the application might handle those methods differently.
Save several comparable results with the date and deployment version. A median can make a small set easier to compare, but retain the individual values and unusual failures. A single central number can hide the slow intermittent requests your visitors actually notice.
Instrument the application without exposing private details
Server-side tracing can identify work that browser timing cannot separate. Look for database queries, template rendering, upstream requests, cache reads, worker queueing and filesystem access. Name the stages consistently across releases so a change can be compared without reconstructing the instrumentation.
The Server-Timing response header exposes named durations to browser tooling. This complete PHP example measures generation of a small public HTML response. It uses hrtime, available in PHP 7.3 and later; production deployments should use a currently supported compatible runtime.
<?php
declare(strict_types=1);
$started = hrtime(true);
$title = htmlspecialchars('Performance example', ENT_QUOTES, 'UTF-8');
$html = '<!doctype html><html lang="en"><meta charset="utf-8">'
. '<title>' . $title . '</title><h1>' . $title . '</h1></html>';
$durationMs = (hrtime(true) - $started) / 1e6;
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-store');
header('Server-Timing: render;dur=' . number_format($durationMs, 3, '.', ''));
echo $html;The duration is measured when the example runs; no benchmark is implied. The example's no-store policy keeps this diagnostic response out of HTTP caches. It is not a recommended policy for every public page.
Place timers around real operations in your application rather than labeling the whole request as database time. Parallel operations may overlap, so their durations do not necessarily sum to total response time. Time spent waiting for an available worker can also occur before your application timer begins.
Use coarse names such as render or database. Do not expose SQL statements, access tokens, customer identifiers, internal hostnames or sensitive business data in public headers. Detailed traces belong in appropriately controlled monitoring systems.
Choose the cache that removes the expensive work
Page caching, object caching and opcode caching solve different problems. They can coexist, but enabling one does not establish that the others are present or effective.
| Cache | Reuses | Work it can avoid |
|---|---|---|
| Full-page cache | An eligible HTML response | Rebuilding that public page |
| Object or data cache | Query results or application objects | Repeated retrieval or computation |
| PHP opcode cache | Compiled PHP instructions | Recompiling the same script |
| Browser cache | Cacheable responses on the visitor's device | Some repeat requests and transfers |
| CDN edge cache | Eligible responses near visitors | Origin trips for cache hits |
For a publication serving the same article to anonymous visitors, full-page caching is often a useful starting point. Check how the cache is invalidated when an editor changes content. A fast stale article after a correction is a publishing failure, even if its performance report looks excellent.
For dynamic pages, an object cache can reduce repeated data work while the application still builds a personalized response. In WordPress, the default object cache is not automatically a persistent cache across requests. A persistent backend requires an appropriate implementation, and the benefit depends on what the application actually caches.
PHP OPcache addresses repeated compilation, not slow queries or distant network calls. Check its configuration and runtime compatibility, but do not expect it to repair an inefficient application design. On a managed platform, ask which caches the provider controls before adding overlapping layers.
Browser caching mainly helps reuse after resources have already been received. It cannot guarantee a fast first visit for a new reader. See the browser caching guide for the difference between freshness, validation and preventing storage.
Protect sessions, carts and personalized content
Start shared HTML caching with a narrow allowlist of public pages. Exclude account, cart, checkout and other personalized routes unless the application has a deliberately designed and tested caching strategy for them. Session cookies and authorization need explicit treatment in your cache rules.
A cookie alone is not a universal guarantee that every intermediary will treat a response as private. Read the behavior of your CDN and application cache, then verify it. Be particularly careful with rules that force caching despite response headers or that ignore query parameters without understanding their meaning.
Test with two separate sessions and a logged-out browser. Confirm that neither receives another visitor's name, basket contents, pricing or account state. A useful cache-hit rate is irrelevant if the cached response belongs to the wrong person.
Keep cache keys understandable. Parameters used only for campaign attribution may unnecessarily fragment public content, but product selectors, currency, language and access state may change the response. Normalize only inputs you have established do not affect the content or authorization.
Fix the slow origin path even when the cache works
Cache misses still happen. New content, unpopular URLs, invalidation and traffic arriving at a different edge location can all require fresh work. A cache that hides a slow origin during your usual test does not remove the need to understand that origin.
Use query profiling to identify expensive or repeated database work. Inspect execution plans before adding indexes. An index that helps one read pattern consumes storage and can affect writes, so make the change against a measured query rather than treating more indexes as an automatic improvement.
Look for repeated calls inside loops, unnecessary data retrieval and expensive work performed on every page view. Move background tasks out of the critical response path where the application's correctness allows it. A page should not wait for unrelated bookkeeping simply because the code happens to share one request handler.
External APIs need timeouts, appropriate caching and failure behavior. Decide which data is essential to the first response and what can arrive later. Deferring important content may affect rendering and usability, so evaluate the complete user task instead of optimizing TTFB in isolation.
Compare runtime and dependency versions in staging before upgrading. A supported PHP or Node release is part of maintenance, but compatibility and performance must be checked with your application. Do not publish a blanket promise that switching versions produces a particular percentage improvement.
Use a CDN where distance and reuse justify it
A CDN can serve eligible content from an edge location closer to the visitor. That can reduce the need to travel to a distant origin, especially for cache hits. However, a CDN configured to cache only static assets may leave every HTML request dependent on the same slow origin.
Inspect the actual response and the provider's documented cache-status headers. Their names and meanings vary. Confirm whether a response was a hit, a miss, bypassed, revalidated or served stale under a configured policy. Do not infer a hit merely from the presence of a CDN hostname.
Measure HTML and static-resource cache behavior separately. A strong hit ratio for images can coexist with poor HTML reuse. Include bytes and request types in the analysis where available; an aggregate percentage can conceal the traffic class you are trying to improve.
Plan invalidation before extending lifetimes. Publishing, correcting, changing access rules and deploying a new build all need predictable behavior. Our CDN and edge caching guide covers these tradeoffs without assuming that every provider uses the same defaults.
Treat protocol changes as one part of delivery
HTTP/2 multiplexing and HTTP/3's QUIC transport can improve how requests share connections. Their impact depends on the connection, network and server implementation. Neither protocol removes slow database work or guarantees a faster first byte for every request.
Connection reuse and TLS session resumption can reduce repeated setup work under suitable conditions. Check what your hosting and CDN already provide before changing server settings. A browser-facing CDN connection and the CDN-to-origin connection can use different protocols.
HTTP 103 Early Hints can let a supporting client start work on important resources before the final response arrives. It does not make the final HTML generation instant, and support depends on the browser and intermediary path. Use it for a demonstrated discovery delay, with a fallback that still works without the hint.
Early Hints can also change what a first-byte measurement represents. Current Chrome behavior counts the interim response in responseStart, while finalResponseHeadersStart, where available, identifies the start of the final response headers. Record the browser and timing field when comparing such setups; an earlier interim response does not prove that the final HTML arrived sooner.
Compression primarily reduces transferred bytes. On-the-fly compression can also consume server CPU, so evaluate its effect rather than claiming that smaller output necessarily means less first-byte latency. The HTTP/2 and HTTP/3 explainer helps separate transport improvements from application improvements.
Decide when hosting is the bottleneck
Investigate infrastructure when slow responses correlate with exhausted workers, CPU saturation, memory pressure, storage latency or database contention. Correlation with busy periods is a useful lead, but identify the constrained resource before choosing a larger plan.
Compare a simple static response with a representative uncached application response, keeping the delivery path comparable. If only the application is slow, inspect its dependencies and execution. If both deteriorate under load, look at shared resource constraints and the hosting path.
On shared hosting, you may not have access to every metric. Bring the provider concrete evidence: timestamps, affected URLs, cache state, response headers and repeated timings. Ask which limits were reached and whether the plan exposes the configuration needed for the proposed fix.
Verify the improvement on the path that failed
Repeat the original slow scenario after changing one relevant part of the system. Check status codes, content correctness, session isolation, invalidation and error handling as well as timing. Then verify that the improvement reaches content rendering instead of merely moving work later.
Use the PageSpeed analyzer when enabled to inspect a public URL, and keep a record of the lab conditions and available field data. Continue with the server performance guides once the next bottleneck is clear. The successful outcome is a repeatable faster response for the intended visitor, with the correct content still intact.