TTFB: what is the Time to First Byte and how to optimize it?
TTFB (Time to First Byte) measures the delay between an HTTP request and the first byte of response received by the browser. Google targets < 800 ms in field data (P75). The most common causes: no page cache, cache dilution from query parameters, unoptimized database queries, no CDN. On an SFCC e-commerce site, cache key normalization reduced dilution by 80% and brought Server Response from 0.74 s to 0.63 s (−15%) in field data.
Time to First Byte measures the delay between an HTTP request and the first byte returned by the server. Google's bar is under 800 ms at P75 in field data. On the ground, I keep running into the same culprits: no page cache, a cache diluted by URL parameters, SQL queries without indexes, or no CDN. A full-page cache brings server response between 20 and 50 ms; a well-configured CDN extends that gain to every region. On an SFCC luxury e-commerce site, normalising the cache keys cut dilution by 80% and dropped Server Response from 0.74 s to 0.63 s (−15%) in field data.
TTFB: definition and Google thresholds
TTFB measures the time elapsed between the moment the browser sends an HTTP request and the moment it receives the first byte of the server's response. This delay has three components: network latency (DNS + TCP + TLS round-trip), server processing time (application execution, database queries, response rendering), and any server-side queuing.
Google defines three performance levels for TTFB:
| Level | Threshold | Status |
|---|---|---|
| Good | < 800 ms | Green |
| Needs improvement | 800 ms to 1,800 ms | Orange |
| Poor | > 1,800 ms | Red |
These thresholds apply to field data at the 75th percentile (P75): 75% of real visits must come in under 800 ms to be considered good.

TTFB's place in the network waterfall
TTFB is the first phase of page loading. In the navigation waterfall, it comes before everything else: the HTML parser cannot start until the first byte has arrived, critical resources (CSS, fonts, LCP image) cannot be discovered before parsing, and LCP cannot fire until the visual element is rendered. A TTFB of 800 ms consumes 800 ms of the LCP budget before the browser has even started working. If the LCP target is 2.5 s, a TTFB of 1.2 s leaves only 1.3 s for everything else.
How to measure TTFB
Chrome DevTools (one-off diagnostic)
Open DevTools (F12), go to the Network tab, click on the first HTML request, then check the Timing panel. The "Waiting for server response" line is the pure server processing time. Use case: quickly identify whether the problem comes from the network (high DNS/TCP/TLS) or the server (high Waiting). A "Waiting" time of 900 ms with normal DNS/TCP/TLS indicates an application-level problem.
WebPageTest (controlled benchmark)
WebPageTest measures TTFB from agents located in specific cities, under simulated network conditions (Moto G4, 4G). The point: reproducing the same conditions from one run to the next to benchmark reliably. For a French e-commerce site, running from "Paris, France" on the mobile profile gives the reading that matters. And running in parallel from Singapore or São Paulo reveals in a minute whether your CDN really covers the world: 1.2 s in Paris and 3.8 s in Singapore is a missing or misconfigured CDN.

Google Search Console (P75 field data)
Search Console reports TTFB via CrUX, aggregated over a rolling 28-day window at P75. It's the only view that matters for SEO decisions: what your users actually experience, across all networks and locations. If WebPageTest says good and Search Console says poor, the cause is almost always one of two: a CDN with poor coverage over the regions where your audience lives, or a server that degrades under the load of real traffic. Trust the field.

The 5 main causes of high TTFB

1. No page cache
This is the most common and most impactful cause. Without a cache, every request triggers the full application stack: routing, authentication, database queries, template rendering, response serialization. On a standard CMS or e-commerce site, this represents 300 ms to 2 s depending on complexity. With a full-page cache, the same response is served from memory in 5–50 ms.
2. Cache dilution from query parameters
A cache is in place, but the cache hit rate has collapsed. The cause is each combination of URL parameters — ?color=red&size=L&sort=price_asc — generating a distinct cache key. On an e-commerce catalog with 20 filters of 5 values each, that produces thousands of combinations, the overwhelming majority of which will never be warmed. Most requests end up as cache misses and TTFB stays high despite a cache that's supposedly "in place".
3. Slow or unindexed database queries
A product page that loads 5 blocks of dynamic content (recommendations, stock, reviews, personalized prices, faceted navigation) can trigger 20 to 50 SQL queries. Without an appropriate index on filtered columns, each query performs a full table scan. On a catalog of 500,000 products, a non-indexed query on product_category_id can take 800 ms on its own.
4. No CDN or CDN not configured for caching
Even with a perfect server cache, network latency is irreducible. Between a server in France and a user in Singapore, the network round-trip alone adds 150–200 ms. With 3–4 round-trips for DNS + TCP + TLS + request, the mechanical TTFB reaches 600–800 ms before the server has even processed anything. A CDN with edge caching eliminates this problem by serving the response from a local node.
5. Heavy synchronous blocking computations
Some processing runs synchronously in the critical path: personalized price calculation, blocking third-party API calls (translation, personalization, real-time recommendations). A third-party API call with a 2 s timeout in the synchronous path sets the minimum TTFB to 2 s on failure. The solution is to cache these results or move them to an asynchronous flow.
Optimizing TTFB on the server side
Full-page cache
A full-page cache serializes the final HTML response and stores it in memory (Redis, Memcached) or on disk. Subsequent requests to the same URL are served from cache, without touching the database or the application layer. Typical gain: from 800 ms–2 s without cache to 20–80 ms with Redis cache. On Laravel, Nginx FastCGI Cache or Varnish, the setup is immediate for public pages without personalization.
// Laravel: simple page cache with Redis
Route::get('/product/{slug}', function ($slug) {
return Cache::remember("page:product:{$slug}", 3600, function () use ($slug) {
$product = Product::with(['images', 'variants', 'category'])
->where('slug', $slug)->firstOrFail();
return view('product', compact('product'))->render();
});
});
Cache key normalization (anti-dilution)
The goal is to reduce the number of distinct cache keys by excluding parameters that don't change the served content. A color filter selected in JavaScript doesn't modify the raw HTML of the page; only the client-side UI selection changes.
// Build a normalized cache key: exclude non-structural parameters
function buildCacheKey(Request $request): string {
$structuralParams = ['page', 'category', 'brand']; // influence content
// Excluded parameters: color, size, sort, utm_source, ref...
$params = $request->only($structuralParams);
ksort($params); // alphabetical order to avoid duplicates
return 'page:' . $request->path() . ':' . md5(serialize($params));
}
Database optimization
Two high-impact actions: indexing filter columns and reducing the number of queries per page.
-- Composite index for product listings filtered by category and price
CREATE INDEX idx_products_category_price
ON products (category_id, price, status)
WHERE status = 'active'; -- partial index: ignores inactive products
Use EXPLAIN ANALYZE (PostgreSQL) or EXPLAIN (MySQL/MariaDB) to identify full table scans before indexing. A full scan on a table of 500,000 rows consistently costs more than 200 ms.
PHP and SFCC: reducing application processing time
On native PHP, enabling OPcache eliminates script recompilation on every request (60–80% gain on PHP execution time). On SFCC, caching pipelines via Business Manager lets you control which routes use the application cache and with what TTL. Custom cartridges with synchronous API calls in the render pipeline are the number-one cause of high TTFB on SFCC.

The SFCC cache that wasn't caching a thing.
On a luxury brand's site, catalogue of several thousand SKUs, their Server Response was oscillating between 0.7 and 0.9 s in field data. The SFCC application cache was activated, configured, monitored — on paper, everything was fine. I opened the cache logs: hit rate close to zero. The cause was hiding in three URL parameters — color, size, sort — each generating a distinct key. On a catalogue with 30 possible filters, that multiplies the number of "unique" pages to cache by 30, 95% of which are never visited: as many entries that will never warm up. I excluded these parameters from the key computation via SFCC directives, adjusted TTLs per page type, and triggered a targeted warmup on the most-visited combinations. Over two months of measurement, dilution dropped by 80%, and average Server Response went from 0.74 s to 0.63 s in field data. A 15% gain, without touching the infrastructure. The takeaway: a cache that's "in place" tells you nothing until you've looked at its real hit rate — a mis-calibrated cache costs as much as no cache at all.
Reducing TTFB with a CDN
Edge caching
A CDN with edge caching stores the HTML response as close as possible to users. When a user in Tokyo loads a page, the response is served from a Tokyo node, not from a server in Paris: network latency drops from 150–200 ms to 5–20 ms. The condition for this to work: the response must be cacheable (Cache-Control: public, max-age=3600). A response with Set-Cookie or Cache-Control: private will not be edge-cached and will always reach the origin.
# Nginx: headers to enable CDN edge caching on product pages
location ~* ^/product/ {
add_header Cache-Control "public, max-age=3600, stale-while-revalidate=300";
add_header Vary "Accept-Language"; # vary by language only
proxy_hide_header Set-Cookie; # prevent cookies from blocking CDN cache
proxy_pass http://backend;
}
Cloudflare and Akamai: advanced configuration
Query parameter normalization can also be configured directly at the CDN level. The Cache Rules available on Cloudflare let you define precisely which parameters enter the edge cache key: ignoring sort and UI filter parameters drastically reduces the number of distinct entries, exactly like application-side normalization.
On high-traffic infrastructure, Akamai's configuration provides fine-grained control: SureRoute optimizes the network path to the origin server, Property Manager manages the edge cache key, and the Cache-Control Modification Behavior overrides origin cache headers without touching application code. A cache hit ratio below 85% on product pages is the first signal of cache dilution or a TTL that is too short.
HTTP 103 Early Hints
HTTP 103 Early Hints lets the server send Link: rel=preload directives before the complete 200 response is ready. The browser preloads critical resources (CSS, fonts, LCP image) while the server is still generating the page. On a TTFB of 600 ms, Early Hints can preload the critical CSS and brand font in parallel, reducing LCP by 200–400 ms without touching the TTFB itself. Nginx has supported HTTP 103 since version 1.25.1; Cloudflare and Akamai pass it through natively from their edges without any server configuration.
For a full analysis of TTFB in the context of a web performance audit or a global server optimization plan, these resources cover prioritization and next steps.
Is TTFB a Google ranking factor?
Indirectly. TTFB is not a direct ranking signal, but it influences LCP, which is a Core Web Vital integrated into the Page Experience Signal since 2021. A high TTFB delays the rendering of the LCP element, which degrades the field score. With equivalent content and backlinks, the site with the lowest TTFB has the advantage on competitive queries.
What is the difference between TTFB and LCP?
TTFB measures the delay until the first byte of the HTTP response — pure server performance, before the browser has even started parsing. LCP measures the moment the largest visible element arrives in the viewport, on the user side. LCP breaks down into four phases, of which TTFB is the first: a TTFB of 800 ms already consumes 800 ms of your LCP budget before any browser processing. If your LCP target is 2.5 s, only 1.7 s remain for everything else.
My TTFB is good in WebPageTest but poor in Search Console — why?
WebPageTest simulates a single location under deterministic conditions. Search Console aggregates 28 days of real data at P75, across all locations and all networks. The gap often reveals a misconfigured CDN (no edge caching in certain regions) or a TTFB that degrades under load. Rely on field data for decisions.
How long does it take to see the impact of a TTFB fix in Search Console?
Search Console uses a rolling 28-day window. After a fix, allow 4 to 6 weeks before the improvement is reflected in the Core Web Vitals report. CrUX data is updated monthly. If you use a RUM (Real User Monitoring) tool, the impact is visible within the first few hours.
Can you achieve a TTFB under 200 ms without a CDN?
Yes, but only for users geographically close to the server. A well-configured server-side page cache can get down to 20–50 ms from the same region. From another region (server in France, user in Singapore), network latency alone adds an irreducible 150–200 ms. A CDN is the only way to achieve low TTFB globally.
How do query parameters affect TTFB on an e-commerce site?
Each unique parameter combination (filters, sorts, colors) can generate a distinct cache key. On a catalog with 20 filters of 5 values each, that means thousands of cache entries that will never be warmed. The majority of requests end up as cache misses and reach the application server, nullifying the effect of the cache despite its presence.
What TTFB should a French e-commerce site aim for?
Google sets the "good" threshold at under 800 ms at P75 in field data. That's the floor, not the target. The best French e-commerce sites I work with aim for under 400 ms at P75, and 80 to 200 ms on European visitors thanks to a well-configured edge CDN and a full-page cache at the origin. To benchmark, run a WebPageTest from Paris on the mobile profile (Moto G4, 4G): that's the calibration that lets you compare your performance to competitors under identical conditions.
Sources
- Web Vitals — Time to First Byte (TTFB) — Google web.dev
- Optimize TTFB — Google web.dev
- HTTP 103 Early Hints — MDN Web Docs
- CrUX Dashboard — Chrome Developers