agentspeed.
← all fixes
Issue remediation

Slow server response (high TTFB)

Your server takes too long to return the first byte, so agents time out before reading your page.

failed checkperformance.ttfb_msperformance.full_render_msperformance.payload_kb
What this means

Time to First Byte (TTFB) is the gap between when an agent makes a request and when your server starts sending back HTML. AI crawlers run with strict budgets, typically 3–8 seconds total per page. If your TTFB is 4 seconds, the agent has roughly 0–4 seconds left to download, parse, and move on; many will abandon the request entirely. "Slow server response" usually means TTFB > 1.5s, full-render > 5s, or payload > 1MB, any of which can cause an agent to drop your page from its index.

Why it matters for AI agents

Agents are not patient browsers. They run thousands of fetches in parallel, and a slow page just gets retried less often (or skipped). The cost compounds: a slow page is fetched less often → updates take longer to propagate → cited content goes stale → the agent loses confidence and stops citing the domain. Fast TTFB is the prerequisite for everything else on this list; the best llms.txt in the world does not help if half your pages time out.

Business impact

Pages with TTFB > 1s are excluded from many real-time agent surfaces (ChatGPT browse, Perplexity live results) because they blow past the per-fetch budget. Slow pages also degrade SEO (Core Web Vitals), increase hosting costs (queued requests cost CPU), and hurt human conversion. Speeding up the server is one of the highest-leverage performance fixes: once-and-done, applies to every page on the site, and the gains stack with caching and CDN strategy.

How to check manually

Run `curl -o /dev/null -s -w 'TTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n' https://your-domain.com/`. TTFB above 1 second is concerning, above 2 seconds is a problem. Or open DevTools → Network → click the document request → Timing tab; look at "Waiting for server response (TTFB)". WebPageTest and PageSpeed Insights will both surface the number alongside diagnostics.

The exact fix

TTFB has three causes, ranked by frequency: (1) server-side rendering work that recomputes per request, fixed with caching (full-page cache, ISR, edge cache); (2) database queries on the hot path, fixed with query caching, indexes, and N+1 elimination; (3) origin geographically far from agents, fixed by putting a CDN in front of the origin so agent fetches hit edge POPs instead of your origin every time. Address (1) first; it is usually the biggest win.

Copy-paste snippet
Reference snippettxtcache-headers.http
# HTTP response headers for a public, cacheable page.
# CDNs and agent caches read these to decide whether to refetch.

Cache-Control: public, max-age=300, s-maxage=3600, stale-while-revalidate=86400
ETag: "v3-2025-04-12"
Vary: Accept-Encoding

# max-age=300        — browsers/agents reuse for 5 min
# s-maxage=3600      — shared caches (CDN) reuse for 1 hour
# stale-while-revalidate=86400 — serve stale for up to 1 day while
#   refetching in the background; near-zero TTFB on cache miss
Platform-specific implementations

The reference snippet above is platform-agnostic. Below are the concrete steps for the four most common stacks plus a generic fallback for any other host.

Next.js

Use ISR (incremental static regeneration) for content pages: set `export const revalidate = 60` on a page.tsx and Next regenerates the static HTML at most once per minute. For the App Router, use the same `revalidate` export or the unstable_cache/cache helpers around expensive functions. Deploy to a host with edge caching (Vercel, Netlify, Cloudflare Pages) so the regenerated HTML is served from a POP near the agent. Add `Cache-Control` headers to dynamic routes too.

Next.jstsxapp/products/[slug]/page.tsx
import { unstable_cache } from 'next/cache';
import { getProductFromDb } from '@/lib/products';

// Regenerate the page in the background at most once a minute.
export const revalidate = 60;

// Cache the DB lookup separately so it can be reused across requests
// even when the page is revalidating.
const getProduct = unstable_cache(
  (slug: string) => getProductFromDb(slug),
  ['product'],
  { revalidate: 60, tags: ['products'] },
);

export default async function ProductPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const product = await getProduct(slug);
  return <article>{/* … */}</article>;
}

WordPress

WordPress is dynamic by default; every request hits PHP and the DB. The fix is full-page caching at the edge: put Cloudflare or Bunny CDN in front of your origin and configure the cache to store HTML responses (not just static assets). Combine with a server-side cache plugin (W3 Total Cache, WP Super Cache, LiteSpeed Cache, or Cloudflare's APO) so even uncached requests are fast. Disable cache on logged-in admin sessions only.

WordPressapache.htaccess
# Tell Cloudflare / a downstream CDN that anonymous HTML is cacheable.
<IfModule mod_headers.c>
  <FilesMatch "\.(html|htm)$">
    Header set Cache-Control "public, max-age=300, s-maxage=3600, stale-while-revalidate=86400"
  </FilesMatch>
</IfModule>

# Bypass cache for admin / preview / cart cookies.
<IfModule mod_rewrite.c>
  RewriteCond %{HTTP_COOKIE} (wordpress_logged_in_|wp-postpass_|comment_author_) [NC]
  RewriteRule .* - [E=NO_CACHE:1]
  Header set Cache-Control "private, no-store" env=NO_CACHE
</IfModule>

Shopify

Shopify origin is already on a globally distributed CDN, so TTFB is rarely the bottleneck on the Shopify side. The most common slowdown is third-party scripts and apps that block server-side rendering: Klaviyo flows, review aggregators, geolocation redirects. Audit installed apps and remove anything you don't actively use. For custom Liquid sections, avoid heavy `{% for product in collections.all.products %}` loops on the homepage; use {% paginate %} or `limit:` to bound the work.

Shopifyliquidsections/homepage-products.liquid
{%- comment -%}
  Bad: iterates every product in the collection at render time.

  {% for product in collections.all.products %}
    <h3>{{ product.title }}</h3>
  {% endfor %}

  Good: explicit limit. Renders fast even for large catalogues.
{%- endcomment -%}
{% for product in collections.featured.products limit: 12 %}
  <a href="{{ product.url }}">
    <h3>{{ product.title }}</h3>
    <p>{{ product.price | money }}</p>
  </a>
{% endfor %}

Webflow

Webflow hosts on AWS CloudFront and serves static HTML, so TTFB is almost always sub-100ms. The slowness, when it appears, is in custom code: a third-party widget that blocks render, or an Embed block making a runtime API call. Open Page settings → Custom code and audit anything in <head>. Move blocking scripts to "Before </body>" or load them async/defer.

WebflowhtmlPage settings → Custom code → Before </body>
<!-- Slow analytics or chat widgets go here, async, with defer.
     They run after the main HTML has rendered, so agent TTFB stays
     fast and the widgets load when the browser has spare cycles. -->
<script async defer src="https://cdn.example.com/widget.js"></script>

Static HTML / any stack

Static sites already have the lowest TTFB possible; the CDN serves a pre-built file. The only failure modes are misconfigured caching (no Cache-Control header, so every request hits origin) and heavy build-time work that delays deploys. For the cache fix, set headers per-host (netlify.toml, vercel.json, _headers file). For build-time, switch to incremental builds where supported (Next ISR, Astro incremental, Eleventy --incremental).

Static HTML / any stacktomlnetlify.toml
[[headers]]
  for = "/*"
  [headers.values]
    Cache-Control = "public, max-age=300, s-maxage=3600, stale-while-revalidate=86400"

# Long-lived cache for fingerprinted assets (Next.js _next/static, etc.)
[[headers]]
  for = "/_next/static/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"
Common mistakes
How to re-test

Re-run `curl -w 'TTFB: %{time_starttransfer}s\n' https://your-domain.com/` from at least two regions (use a remote VM if your laptop is on the same continent as origin). Aim for sub-300ms TTFB on cached pages, sub-1s on uncached. Run a fresh AgentSpeed scan, and TTFB and full-render checks should pass. PageSpeed Insights and WebPageTest will corroborate.

FAQ
What TTFB should I aim for?

Under 200ms for cached, under 800ms for uncached. Google's Core Web Vitals threshold is 800ms; agent crawlers are typically stricter, so sub-300ms is a safe target for citation reliability.

Does HTTP/2 or HTTP/3 help with TTFB?

Marginally. They reduce connection-setup time but not server processing time. The bigger wins are caching and origin proximity. Enable HTTP/2 and HTTP/3 anyway; they help downstream metrics (full-render, payload).

How do I know which fix to do first: caching, DB, or CDN?

Run two tests: one cold (cache-busting query string) and one warm (regular fetch). If cold-vs-warm differ a lot, you need caching. If they are both slow, you need DB / origin work. If warm is fast at the origin but slow from a remote region, you need a CDN.

Verify on your site
Run a scan

Free scan, no signup. The score page is permanent and citable, so you can link it from your team's remediation ticket alongside this guide for “Slow server response (high TTFB)”.

Run a free scan →See all fixes →