---
title: "Slow page response times - Serpwise"
description: "Slow TTFB delays every later rendering milestone and can reduce crawl efficiency at scale. Separate network time from origin work before choosing a fix."
url: "https://serpwise.ai/learn/slow-page-response-times/"
source: "https://serpwise.ai/learn/slow-page-response-times/"
---
[← Back to Learn](/learn/)

Crawling & Indexing Warning

# Slow page response times

Slow TTFB delays every later rendering milestone and can reduce crawl efficiency at scale. Separate network time from origin work before choosing a fix.

Time to First Byte (TTFB) is the time between the crawler sending the request and your server returning the first byte. It’s the floor for every other speed metric - you can’t have a 2-second LCP if TTFB alone is 2.5 seconds.

Common field-performance guidance, measured at the 75th percentile, is:

- **Good**: TTFB &lt; 800 ms
- **Needs improvement**: 800 ms - 1800 ms
- **Poor**: &gt; 1800 ms

TTFB is not a Core Web Vital, but it feeds later metrics such as FCP and LCP. On large or frequently changing sites, slow or unstable server responses can also reduce crawl efficiency. There is no universal response-time threshold that guarantees a particular crawl rate.

## How to detect it

```
curl -o /dev/null -s -w \
  "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
  https://example.com/
```

The number that matters most for crawlers is `time_starttransfer` minus `time_appconnect` - that’s pure server work, network neutralized.

Three signals worth checking together:

1. **CrUX TTFB at 75th percentile** (PageSpeed Insights, real-user data)
2. **Sampled crawler TTFB** (Search Console → Settings → Crawl stats → Avg response time)
3. **Lab TTFB** (curl from the same region as your origin)

A gap between CrUX and lab means real users hit different edges or different cache states. A gap between Search Console and lab means Googlebot is hitting cold paths.

## The fix - find the actual cost

Sources of slow TTFB, ordered by frequency:

1. **Database query inside the request path** - N+1 queries, missing indexes, joins on cold tables.
2. **Cold starts on serverless** - first request to an idle function pays minutes-old container init.
3. **Synchronous third-party calls** - calling an analytics or auth API in the request handler, blocking on its response.
4. **Origin without a CDN** - every request traverses the public internet to one machine.
5. **Render fan-out** - the page makes 50 internal HTTP calls to build itself.

### Universal - add a CDN cache layer

The cheapest TTFB fix is to serve already-rendered HTML from an edge cache. Set explicit cache headers:

```
Cache-Control: public, s-maxage=300, stale-while-revalidate=86400
```

`s-maxage` is for shared caches (CDNs). `stale-while-revalidate` lets the CDN serve a slightly stale copy while it refreshes - TTFB stays low even when the page changes.

For pages that legitimately can’t be cached (logged-in user pages, personalized homepages), the fix is to make the origin work faster, not to cache.

### WordPress

Order of impact:

1. Add an object cache (Redis or Memcached) - `wp-config.php` constant `WP_CACHE`, plus a drop-in like Redis Object Cache.
2. Add a full-page cache (WP Rocket, LiteSpeed Cache, or Cloudflare APO).
3. Audit plugins - `query-monitor` will show you the slowest DB queries per request. Disable or replace plugins that scan `wp_options` on every load.

### Shopify

Shopify’s origin is already fast. Slow TTFB on Shopify is almost always one of:

- A theme that makes synchronous calls to a third-party app from `theme.liquid`.
- A bloated app that injects script and waits for it to evaluate before the page completes.

Audit with `?view=performance` query params on a few key pages, or use the Shopify performance debugger in the admin.

### Next.js (App Router)

Use static generation where possible (`force-static` route segment config). For dynamic pages, enable PPR (Partial Pre-Rendering) or ISR via `revalidate`:

```
// app/products/[slug]/page.tsx
export const revalidate = 3600; // ISR - refresh every hour

export default async function Page({ params }: { params: { slug: string } }) {
  const product = await getProduct(params.slug);
  return <Product product={product} />;
}
```

For RSC pages, audit your `await` chain. Parallelize independent fetches:

```
// before - serial, slow
const product = await getProduct(slug);
const reviews = await getReviews(slug);

// after - parallel
const [product, reviews] = await Promise.all([
	getProduct(slug),
	getReviews(slug),
]);
```

### Nginx (as a microcache)

A 30-second microcache in front of a slow origin is a one-line fix that hides almost any spike:

```
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mc:10m max_size=1g;

server {
  location / {
    proxy_pass http://origin;
    proxy_cache mc;
    proxy_cache_valid 200 30s;
    proxy_cache_use_stale updating error timeout;
    add_header X-Cache $upstream_cache_status;
  }
}
```

Cacheable requests can avoid repeated origin work. Actual TTFB still depends on cache state, network path, processing time, and visitor location.

## Pitfalls

**Don’t optimize the wrong layer.** TTFB at the browser includes DNS, TLS, network, and server. If your TTFB is 1.2s and 800ms is TLS handshake from a faraway region, optimizing your database won’t help. Measure first.

**Don’t cache personalized content blindly.** A logged-in dashboard cached for an anonymous bot is a data leak. Vary by `Authorization` header or by session cookie.

**Don’t ignore third-party scripts at the document level.** A `<script src="…">` in `<head>` that blocks parsing doesn’t move TTFB, but it gates every other metric. Defer or lazy-load anything below-the-fold.

**`stale-while-revalidate` is your friend.** Most pages don’t need to be perfectly fresh. Letting the CDN serve a 5-minute-old version keeps TTFB low even during a refresh.

## Fix at the edge with Serpwise

When the origin is genuinely slow and re-architecting is a quarter-long project, the edge does the work for you.

Serpwise caches HTML at the edge with control over the cache key, respects configured origin behavior, and can serve eligible cached content without repeating the full origin request. Actual response time varies by location, cache state, and network conditions.

[See pricing](/pricing) or run a [free AI visibility audit](/audit).

From diagnosis to deployment

## Find the issue. Ship the fix.

Use Learn to understand the problem, then run Serpwise against your own site to see what can be approved and deployed.

[Run free audit](/audit/) [Book a demo](/demo/)